I dont know who may need this at this point but:
@hasanghaforian is correct, and contrary to what @gezdy says here, no, using registerActivityLifecycleCallbacks
is not a solution, no matter how you look at the problem, it doesn't even make sense...
One could... maybe create a working version that uses the registerActivityLifecycleCallbacks
option but it would be unnecessarily complex and slower.
The aim is to:
Proactively retrieve the top most desired Activity.
Now the problem with Hasan's answer and gezdy's answer is that neither acknowledges the fact that, the same way Fragments stack one on top of each other, Activities can ALSO be stacked, so we need a LinkedDeque...
public class ActivityRegistry extends Application {
private final LinkedList<Activity> activities = new LinkedList<>();
public<A extends Activity> boolean register(A activity) {
return !contains(activity) && activities.offerLast(activity);
}
public void unregister() {
activities.pollLast();
}
public<A extends Activity> A getLastActivity(Class<A> componentTYpe) {
Activity current = getLastActivity();
return componentTYpe.isInstance(current) ? componentTYpe.cast(current) : null;
}
public<A extends Activity> boolean contains(A activity) {
return activities.contains(activity);
}
public void clear() {
activities.clear();
}
private Activity getLastActivity() {
return activities.peekLast();
}
}
You must take into consideration that the register(A activity)
method adds ONLY IF object is NOT PRESENT.
Since BOTH answers are registering Activities during the RESUME phase of the lifecycle, and then unregistering them during the DESTROY.
The Registration - Unregistration cycle is NOT a CLOSED LOOP.
This means that if the app goes to the background and then to the foreground again 2 instances will be added, since the RESUMED phase gets called twice without traversing the DESTROY.
My solution prevents that, but another alternative is to register during the onCreate()
phase of the Activity..
Now as to the "Memory Leak" issue from the Activity perspective.
There is NO NEED to assign the context to a field, IF the context can be accessed from a method, IN FACT, methods are provided precisely to avoid MemLeaks, since, if there would be NO danger of it leaking, the variable could be easily passed via constructor parameter.
This is Gezdy's code:
public class MyBaseActivity extends Activity {
protected MyApp mMyApp; //This field will create a Memory Leak
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMyApp = (MyApp)this.getApplicationContext();
//If app context can be accessed via method, we dont need to assign it to a field.
}
protected void onResume() {
super.onResume();
mMyApp.setCurrentActivity(this);
}
protected void onPause() {
clearReferences();
super.onPause();
}
protected void onDestroy() {
clearReferences();
super.onDestroy();
}
private void clearReferences(){
Activity currActivity = mMyApp.getCurrentActivity();
if (this.equals(currActivity))
mMyApp.setCurrentActivity(null);
}
}
Instead do this:
public class MyBaseActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
((ActivityRegistry)getApplicationContext()).register(this);
super.onCreate(savedInstanceState);
}
protected void onDestroy() {
((ActivityRegistry)getApplicationContext()).unregister();
super.onDestroy();
}
}
Now the Activity can be retrieved like this:
MyActivity activity = ((ActivityRegistry)getApplicationContext()).getLastActivity(MyActivity.class);
//If activity returns null, it means the last Activity was NOT of type MyActivity.class.
//If you pass Activity.class instead, it will always get you the last Activity.
//And the you must FORCE CAST into what you believe it to be the type.
Where MyActivity extends MyBaseActivity