Why only the first activity's `onDestroy` is called, not other activities? - android

(I searched quite a bit, but there seems no exact answer for this.)
Let's say there's an app. We can push a button to start another activity.
Like this: Activity1 -> Activity2 -> Activity3
If we use the 'back' button, it calls the finish(), so each activity's onDestroy() gets called.
But, if we close the app(by pushing the 'overview' button and then swipe the app out),
only the Activity1's onDestroy() gets called.
Why the onDestroy() of other activities are not called?
Does it mean that other activities are alive until the system kills them?
(If the system has enough resources, they are not destroyed?)

Ideally when you force close the App from overview, it kills the entire app process and all the activities are destroyed, and your activity stack root's(which is ActivityA) onDestroy method is called and for other activities the method won't be triggered but the stack itself gets destroyed along with the process. Nothing will be alive once the process is destroyed.

Related

Android : Returning to prior Activity

When you're in an an Activity (we'll call it A), and you invoke a subsequent Activity (B), perhaps as a result of clicking a button in A, and then RETURN to that prior Activity A, either by clicking the Back button or explicitly calling finish() from within B, it causes A to be completely rebuilt, calling its constructor and its OnCreate() method, etc.
Is there any way to prevent that from happening, so that it actually does return to the prior, already existing, Activity A?
Correct me if I'm wrong, but it should not call onCreate() here's a gross over simplification, but let's say activity's are managed much like a simple stack, let's call it AppStack
When a onCreate() for Activity A is called, the OS pushes the Activity Instance onto the AppStack
________ _________________
Activity|
___A____|_________________
When you click a button on Activity A, it launches a new intent to Activity B
Intent actB = new Intent(this, ActivityB.class);
and subsequently puts Activity A into Stopped state
When Activity B's onCreate() is called the OS pushes that Activity Instance onto the AppStack
________ __________________
Activity|Activity|
___A____|___B____|_________
Now if you call finish() or super.onBackPressed() in Activity B, the OS will pop() the Activity from the AppStack
________ __________________
Activity|
___A____|__________________
When the OS returns to the previous activity, it sees that it is Stopped and begins the process of Resuming it through onResume().
Now if there is some data that you require to be persistent, you can add it in by Overriding onResume()
Check out the activity lifecycle docs, for more info:
This is by design:
If an activity is paused or stopped, the system can drop it from memory either by asking it to finish (calling its finish() method), or simply killing its process. When the activity is opened again (after being finished or killed), it must be created all over.
See Activity Lifecycle. It's also why the Service class exists:
A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application.
It's not a typical scenario but when onCreate() is called when going back to that activity that means the Android OS kills it in the background.
Reason: Android is experiencing some memory shortage so killing some of the background task will be a must.
Is there any way to prevent that from happening?
No, you don't have a control over it, there are many reasons why its having a memory shortage e.g. other app installed that certain device is consuming more than expected. Although you can handle this use-case by storing the current information in onSaveInstanceState() and recovering the value from onCreate().
Calling finish() on ActivityB or pressing back will just destroy ActivityB.
ActivityA will not be completely rebuilt. This means it will not call onCreate method. It will just call onResume.
This is the normal behaviour.
However, on special situations, the system could destroy ActivityA (maybe because it needs memory to perform another task), so when you go back to it, the system will have to rebuild it.
To simulate this situation, there is a setting that you can check/uncheck, called "Don't keep activities".
If you have it checked, you will be simulating the situation explained above, it will always destroy the ActivityA as soon as it is not shown, and when you come back to it, the system will have to rebuild it calling onCreate.

Activity's onDestroy() method not called after removing activity from background by swiping

I have implemented ActivityLifecycleCallbacks in a private class inside my Application class.
If Home button or Back button is used, lifecycle's onStop() and onPause() methods are getting called. If I kill the activity by swiping out from background, onDestroy() method is not getting called. It gets called when I start my activity next time. I am using moveTaskToBack(true) in case of Back press.
What must be the issue and which lifecycle method should get called when we swipe out from background?
From the documentation of onDestroy():
Note: do not count on this method being called as a place for saving
data! For example, if an activity is editing data in a content
provider, those edits should be committed in either onPause() or
onSaveInstanceState(Bundle), not here. This method is usually
implemented to free resources like threads that are associated with an
activity, so that a destroyed activity does not leave such things
around while the rest of its application is still running. There are
situations where the system will simply kill the activity's hosting
process without calling this method (or any others) in it, so it
should not be used to do things that are intended to remain around
after the process goes away.
Such a situation is swiping the app out of the recent tasks list.
Check out this answer on how to get notified when the app is getting swiped out of Recents.
I remember reading a similar question on StackOverflow. Here was the top answer:
Handle exit application from Task Manager
Handle exit application from Task Manager
Unfortunately there isn't a good answer for handling this situation. If the app is force-killed, onDestroy method isn't necessarily called. According to the documentation.
Note: do not count on this method being called as a place for saving data! For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here.
If you can, clean up in the onPause() method. In order for the user to get to that screen to kill the app, it has to have been backgrounded and thus onPause() would be called. (see documentation)
swiping app from back ground i.e. clearing from recents causes the whole process and task to be killed and that time onDestroy() may not be called , when user presses back from an activity then only that activity is killed not the process.

Is onDestroy always called when android destroys activity to save memory but does not kill App?

I want to use Application.ActivityLifecycleCallbacks to monitor how many activities are there in the back-stack. Can I increment/decrement counter in onCreate/onDestroy to handle this?
onDestroy is NOT guaranteed to be called every time an activity is destroyed.
If the user clicks back to destroy it, onDestroy will be called.
If the user swipes the application from the recent app menu, onDestroy will NOT be called.
If the application crashes, it's undetermined if it'll be called (from my experience, it isn't called).
Is onDestroy always called when android destroys activity to save memory?
Yes
Documentation:
The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.
I want to use Application.ActivityLifecycleCallbacks to monitor how
many activities are there in the back-stack. Can I increment/decrement
counter in onCreate/onDestroy to handle this?
Better to counter in the onStart() and onStop() methods, onCreate() doesn't guarantee visibility. For example if somehow something stopped onStart() from happening.
onDestroy() is the final method that is called on an Activity instance before it’s destroyed and completely removed from memory. In extreme situations Android may kill the application process that is hosting the Activity, which will result in OnDestroy not being invoked. Apparently most of the Activities will not implement this method because most clean up and shut down has been done in the OnPause and OnStop methods.
For more details please visit Android Developers Portal.
(https://developer.android.com/reference/android/app/Activity.html "Android Developers")

onStop vs onDestroy

I have tried to research exactly when the onDestroy method is called for an activity, but I've read some confusing and conflicting information. In general, my question is: under what circumstances is the onDestroy method actually called on an activity? More specifically, if I have two activities, activity A and activity B, if activity A is running and I create an intent and switch to activity B, is activity A only stopped, or is it destroyed?
Like stated in the official documentation:
onDestroy()
The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.
In your example the Activity A is stopped and could be destroyed by the System
Note per documentation link above:
…do not count on [onDestroy()] being called as a place for saving data … [see] either onPause() or onSaveInstanceState(Bundle).
onDestroy() is called whenever:
The user takes out the activity from the "recent apps" screen.
The user takes out the activity from the "recent apps" screen.
onStop() is called whenever:
The user leaves the current activity.
So in your example, when the user launches Activity B, Activity A called onStop().
EDIT:
The onDestroy() method is not always being called, according to the documentation. onStop() is always called beginning with Honeycomb, so move code you explicitly need to do before the activity stops to there.
Starting with Honeycomb, an application is not in the killable state until its onStop() has returned.
https://developer.android.com/reference/android/app/Activity#ActivityLifecycle
Hope this helped :D

android: how to handle onStop method call

If I have a method called onStop and it calls super.onStop();. When does this method run?
In my main activity, I start another activity as follows: startActivity(new Intent(this, MyNewActivity.class));. Does this automatically stop my main activity and call onStop?
Also, what kind of things should I do in the onStop method of my main activity. So far all I have done is unregister listeners to free up space but other than that is there anything else I should do?
Thank you, any help is greatly appreciated.
When does this method run?
This method calls when your Activity is no longer visible to the user
Does this automatically stop my main activity and call onStop
Yes when you start another Activity first onPause() function get called and then onStop().
what kind of things should I do in the onStop method of my main activity
It depends on your implemenetation and your needs but persisting data recommended to implement on onPause() callback function
In my main activity, I start another activity as follows: startActivity(new Intent(this, MyNewActivity.class)); Does this automatically stop my main activity and call onStop?
You can know yourself what happens when you call new activity takes focus just put a simple log statement and check yourself.
http://developer.android.com/guide/components/tasks-and-back-stack.html
Quoting from the docs
When the current activity starts another, the new activity is pushed on the top of the stack and takes focus.
The previous activity remains in the stack, but is stopped. When an activity stops, the system retains the current state of its user interface. When the user presses the Back button, the current activity is popped from the top of the stack (the activity is destroyed) and the previous activity resumes (the previous state of its UI is restored).
onStop()
Called when the activity is no longer visible to the user, because another activity has been resumed and is covering this one. This may happen either because a new activity is being started, an existing one is being brought in front of this one, or this one is being destroyed.
Followed by either onRestart() if this activity is coming back to interact with the user, or onDestroy() if this activity is going away.
Check the topic saving activity state
http://developer.android.com/guide/components/tasks-and-back-stack.html#ActivityState
Note: When the system stops one of your activities (such as when a new activity starts or the task moves to the background), the system might destroy that activity completely if it needs to recover system memory. When this happens, information about the activity state is lost. I believe this happens on priority basis.
If you need to store persistent data do it in onPause
For more info check the activity lifecycle
http://developer.android.com/reference/android/app/Activity.html

Categories

Resources