As I understand it, an activity being destroyed is not equivalently to an activity being finished.
- Finished
- The activity is removed from the back stack.
- It can be triggered by the program (e.g. by calling
finish()), or by the user pressing the back key (which implicitly callsfinish()). - Finishing an activity will destroy it.
- Destroyed
- The Android OS may destroy an invisible activity to recover memory. The activity will be recreated when the user navigates back to it.
- The activity is destroyed and recreated when the user rotates the screen.
- Reference: Recreating an Activity
So how do I finish a destroyed activity? The finish() method requires an Activity object, but if the activity is destroyed, I have no Activity object – I am not supposed to be holding a reference to a destroyed activity, am I?
Case study:
I have an activity a, which starts b, which in turn starts c (using Activity.startActivity()), so now the back stack is:
a → b → c
In c, the user fills out a form and tap the Submit button. A network request is made to a remote server using AsyncTask. After the task is completed, I show a toast and finish the activity by calling c.finish(). Perfect.
Now consider this scenario:
While the async task is in progress, the user switches to another app. Then, the Android OS decided to destroy all 3 activities (a, b, c) due to memory constraints. Later, the async task is completed. Now how do I finish c?
What I have tried:
- Call
c.finish():- Can’t, because
cis destroyed.
- Can’t, because
- Call
b.finishActivity():- Can’t, because
bis destroyed.
- Can’t, because
-
Use
Context.startActivity()withFLAG_ACTIVITY_CLEAR_TOPso as to raisebto the top, thus finishingc:// appContext is an application context, not an activity context (which I don't have) Intent intent = new Intent(appContext, B.class); // B is b's class. intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); appContext.startActivity(intent);- Failed,
appContext.startActivity()throws an exception:
- Failed,
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
Edit: Clarification: I need to wait until the async task finishes and decide whether to finish c based on server’s response.
Can’t finish a destroyed activity directly, so just
finish()it in itsonCreate()(suggested by @Labeeb P). Here’s how:If the activity is already destroyed when trying to finish it, save a boolean flag somewhere instead.
SharedPreferences(suggested by @Labeeb P).In the activity’s
onCreate(), check the flag and callfinish().Calling
finish()inonCreate()is actually a legimate operation, as it is mentioned in the doc:Other considerations:
Of course, an activity being destroyed doesn’t necessary mean that the app is in background (there might be another foreground activity). Still, the above solution (calling
finish()inonCreate()) works.