Understanding of isFinishing()
Asked Answered
H

3

36

I got confused after reading the Android doc about isFinishing() at http://developer.android.com/reference/android/app/Activity.html.

If I call isFinishing() in onPause(), what would the return value of the isFinishing() call be in the following 3 scenarios?

  1. Activity is killed due to finish() being called.
  2. An activity is not in the foreground and the activity (not the app) is being killed by the OS due to low memory.
  3. Activity is going to the background.

I am sure that the result of isFinishing() will be true in scenario 1 and will be false in scenario 3.

How about scenario 2? Will isFinishing() return true or false in scenario 2?

Holm answered 8/3, 2011 at 0:42 Comment(0)
A
27

Your Activity doesn't get killed by the OS while it's in the foreground. That wouldn't make sense.

However, if the activity goes to the background because the user switched to a different app, it could get killed after onPause() has been processed. As such, you could get isFinishing() == false as the user switches to a new app, but then the app is killed.

As the doc says, save all persistent data in onPause(). onDestroy() is not guaranteed to be called.

(I wouldn't be surprised if Dianne steps in and corrects me here, btw.)

Antipope answered 8/3, 2011 at 0:56 Comment(23)
I edited my question and specified that the activity is in background and it is killed by OS. In this case, is isFinishing() still returning false?Holm
If your app is in the background, I'm tempted to say that the process will be killed without any further notice.Antipope
Yeah, Dianne wrote about it here: android-developers.blogspot.com/2010/04/… ... quote: "Once Android determines that it needs to remove a process, it does this brutally, simply force-killing it."Antipope
What I mean is that, an activity is in the background. An app may have multiple activities in the stack. The Android may kill an activity that is not in the foreground. The app itself is in the foreground. In this case, will isFinishing() returns false if the activity that is not int the foreground gets killed by OS?Holm
Android only kills processes. Unless you do something special, all of your activities are running in the same process, so can only all be killed together. Regardless, isFinishing() tells you if the activity is actually finishing. That is, the user can never return to it. This is not the case if it is killed just for being in the background, regardless of how that may be done.Ablative
Thanks hackbod. I didn't know Android only kills processes not individual activities. This issue confused me for a long time. Thanks for clarifying it.Holm
Hi Hackbod, I read more Android doc. Are you sure Android only kills processes? The Android doc says 'A stopped activity is also still alive...... However, it is no longer visible to the user and it can be killed by the system when memory is needed elsewhere.' -- developer.android.com/guide/topics/fundamentals/activities.html. It sounds to me that Android system can kill individual invisible activities.Holm
@Kai: Um.... Dianne WROTE many of the core Android systems. If she doesn't know, nobody does. Besides, it's consistent with what she said. When it says "killed", it means that the activity is killed by having its hosting process killed.Antipope
Thanks, EboMike. Android should really make it clear in doc that Android only kills processes, so we will not write app that keeps a lot of activities in the stack.Holm
Kai, I don't see how this is relevant? Basically, you write your code based around activites. They clean up in onPause. They resume work in onResume. Whether or not (and how) they get killed is normally not a consideration. What situation do you have where that matters?Antipope
I have an activity, say activity A, starts activity B in A.onCreate(). Assume the stack now has A B, with B at the top. Since A is not in foreground, assume OS killed A due to low memory. After a while, B exits after finish() is called. Now A is in the foreground. Since A was killed before, it is recreated. But A.onCreate() starts B again, which is not what I expect. What I expected is that, when B finishes, A is at the top of the stack. So whether A can be killed when invisible makes difference.Holm
Why does A start activity B in onCreate? That sounds fishy. Also, if A starts activity B due to certain data/extras in the intent, it will do so again. Btw, you should always assume that an activity could get garbage collected due to low memory. There's even a setting in the dev tools that will force-delete an activity right after it goes to the background.Antipope
A is a splash screen activity, and B is home activity. A.onCreate() starts an AsyncTask, which will finally starts B. BTW, what dev tools can force-delete an activity right after it goes to the background? This is really what I am looking for.Holm
It's in the "Dev Tools", I think. If you use an emulator, you'll see it. You can move the dev tools APK onto your phone. Personally, I'm not a fan of splash screens. But if you really need to use them, then start the B activity when your AsyncTask is finished and call finish() as you start the activity. Obviously, you WILL see the start screen again if your process is killed.Antipope
Thanks. I saw Dev Tools in emulator and saw Immediately destroy activities option in the tool. I will play it around. BTW, as to splash screen activity A, I can not finish it after it starts B, because we allow users to restart the app later by sending intent with clear-top flag to A. So we have to keep A in the stack.Holm
What does activity A do?! It just sounds wrong, whenever you have a splash screen activity, you'll always want to finish() it after it's moving on to the main activity. If you do want to reset and re-display the splash screen, you can just call startActivity on A.Antipope
A checks whether user logs in or not. If logged in, A starts B. If not logged in, A lets user log in first. Assume the current stack is A B C D E F G. At G, we allow users to log in as a different user by logging out first and then sending intent with clear-top flag to A. So the stack only has A, and A checks login again. After login, A starts B.Holm
Unless you want the "back" button to trigger a re-login, you need to call finish(). If a login is required, each activity will need to check the login status and start A first if the user is not logged in.Antipope
With A at the bottom at the stack, it is easier to clear all other activities, say there are 10 activities in the stack, at once with intent with clear-top flag to A. We check whether the login has expired or not at each activity's onCreate or onResume. If login expires, intent with clear-top flag will be sent to A to clear all activities above A and A shows up again to do login.Holm
How would you save the data into onPause? shouldn't you just use onSaveInstanceState instead?Rosemare
You should definitely finish activity A after login succeeds. If you need it open (due to logout), open it again with clear top. If I login and press back and see the login screen again, that's bad. KISS. @HolmWorked
Is it possible for an activity to get destroyed but never have isFinishing() return true?Puppetry
I'm still confused about whether I should use isFinishing() or isDestroyed() to check whether the activity is really destroyed.Winebaum
Z
1

How to call onPause? 2 ways: The activity goes to background or we call finish() somewhere. If the activity goes to background, isFinishing() is false. If we call finish(), isFinishing() is true. And now see scenario 2: An activity is not in the foreground and the activity (not the app) is being killed by OS due to low memory. An activity will be killed, so it muse be in background, it is paused, so onPause will not called. BTW, an activity cannot be killed, only process can be killed

Zimmerman answered 15/6, 2016 at 11:7 Comment(1)
"the activity (not the app) is being killed by OS" and "BTW, an activity cannot be killed" we need more ))Bodnar
G
-3

isFinishing() returns false in all methods of an activity except onDestroy().
For more information, put logs in all the activity methods like below

Log.i("onCreate",""+isFinishing);
Goodbye answered 7/2, 2020 at 18:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.