First of all, I'm new in android developing...
I had read some article in android API guide and feel confused about the component life cycle with the hosting process.
Here is my understanding:
Android system may kill some activities in a process or the whole process in low memory situations,which means there is a possibility that a started activity may die, but process still alive.
If a service is started and not call any stop method, when in extreme low memory, this service is killed by system with its hosting process, not just the service itself, means this circumstance should not occur:service is killed by system, but hosting process still alive.
When an app starts, the user navigates activity1 -> activity2 -> activity3 and none of them call finish(). Next, the user navigates to another app's activity and plays with it so long that the former app process is killed by the system. Now the user navigate back to activity3 in the back-tracking stack, what will happens? The former app process restarts with only activity3 recreate?
Anything wrong ?
There is no need to switch to another app's activity: from the moment that you leave the first activity to go to the second activity; there is a clear possibility that the first activity might have been destroyed when you return on it from the second activity (back-tracking) and when you go to a third one, either the first one, the second or both of them can be possibly destroyed in the mean time. In fact, you don't even to leave an activity to see it destroyed; as this will automatically happen simply if you switch from the portrait mode to the landscape mode and vice-versa by rotating the device.
When you return to an activity, the onRestart() function will be called if the activity has not been destroyed in the mean time. If it has, the "onCreate(Bundle savedInstanceState)" will be called instead but with the argument "savedInstanceState" set to a non-null value (ie, it will point toward a valid Bundle object) if you have took the precaution of saving the current state of the activity in the "onSaveInstanteState(Bundle outState)" function when the activity has entered the process of being destroyed by the system. The system will always call this function before destroying an activity when this one need to be restored later for back-tracking. Of course, it won't be called after a call to finish() because this will also remove the activity from the back-tracking stack.
Finally, in Android, the coupling between activities in the same application is very loose. When it comes to the use of resources, there is not much of a difference between switching to an activity from the same application or from another application. In many ways, activities will behave like if there were all fully independant applications when it comes to running. This is why you always need to use an intent to start an activity; even when it is from the same application.
Based on my understanding ...
In android during low memory situations, first activities would be removed from memory where the onDestroy method gets called.
This is not the case always. It depends on how the service is started i.e whether from onStart or through Binding the service with a component.
Once the former app process is killed, then when the user launches the application, he will be taken to activity 1. Launching the activity in same task or different task depends on launch modes used (single task, etc)
Related
I'm wondering if Android system is able to kill the activity without the entire application process while the app is minimized. From Android documentation we know that onDestroy is only called when the activity is about to be destroyed and the systems guarantees to call this method whenever it is about to kill the activity, it will not be called only in case the entire application process is killed.
So, imagine such a situation - you send the app to the background(minimize) and after some time the os starts to run low on memory and decides to kill the activity, but since the app is currently suspended and cannot execute code it is not able to call its onDestroy method althought it is guaranteed that it will be called before every activity destruction.
So, this kind of reasoning gives me a thought that while the app is in the background os is only able to kill the entire process but not some specific activities. Is my reasoning correct, or did I miss something?
That's true: while the app is in the background os is only able to kill the entire process but not some specific activities.
Your reasoning is correct.
If the user navigates away from the activity/application (e.g. by pressing the home button) then the activity is said to be in the "Stopped" state. (States being "None-existent", "Stopped", "Paused" and "Resumed"). If android get low in memory and needs to kill some processes it will target those processes whose activities are in the "Stopped" state and it kill the whole process (not the activity). Furthermore, it will not be polite when doing so and therefore, will not call the activity's onDestroy() method.
Edit following comments about the confusion of saved state on process death:
If the activiy's process is killed, the system temporarily saves a set of settings outside the activity and using these settings, it recreates the activity the next time it is launched.
For example, just before moving to the "Stopped" state the system calls onSaveInstanceState(Bundle) on an activity that is not "finished" and saves this Bundle outside the activity. The system also does remember that it killed activity's process while it was not finished. Using these two along with other settings (saved outside the activity), the system recreates the activity.
If, However, the activity is finished (e.g. user presses the back button, swipes away the activity's card from the overview window, Activity.finish() is called explicitly, etc), onSaveInstanceState() is not called and the system doesn't save any settings to recreate the activity next time it's launched. It simply creates a fresh one.
This is good news, why? Becuase if it wasn't the case, the developer would have had to stash key state properties manually outside activities and reinstate them when activities are relaunched (that would've been a nightmare)
Since there's been much confusion on this issue, in large part due to the confusing state of the official docs in the past, here's what the docs say
at present:
The system never kills an activity directly to free up memory.
Instead, it kills the process in which the activity runs, destroying
not only the activity but everything else running in the process, as
well.
This as well as real world observation yields that the answer is no.
https://developer.android.com/guide/components/activities/activity-lifecycle#asem
As we know Android would kill a paused Activity in some conditions. And there is a FIFO back stack of Activities.
My questions are as follows:
How Android kills an Activity without pulling it from the back stack (it might affect the top active Activity)
After killing it, what things are released from this Activity? And can I still get this Activity's instance?
Android does not kill Activities "separately", it kills the whole app process with all Activities.
The only way to get an Activity killed by the system is to set Don't keep Activities flag in device's Developer Options. However this option is just for development, not for applications in release.
Activity can't be killed but Os can kill the whole application. In this case you can try finish()/finishActivity()/context.finish() to finish the activity. While you finish an activity backpress will not return to the previous activity.
System can't kill activity, it can call the whole app.
And when it kills the whole app, it doesn't call any method from activity (onStop(), onDestroy(), etc)
Finally, you can't get activity instance.
I'm new to android system and its related things, I want to know when android removes existing instances of activities and their related bundle and data. And also where those instance are stored in android system?
Edit:
Let's say I start an activity and then return to home screen and not back to stopped activity for many hours. How long android will keep all these existing instances and when removes them?
Android maintains a stack system for storing the activities.
A -> B -> C
Your activity could be destroyed upon pressing the home button if the system is constrained and has determined it needs to free some resources.This only occurs if Android terminates the process. Android does not destroy individual activities in response to memory pressure. The documentation states that onDestroy() can be called if:
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.
You can't determine when it will be destroyed, it's decided by the system when it needs memory so it just kills your app. It's just like GC call, you can never determine when it'll be called, it's controlled by the JVM, similarly this is controlled by the kernel.
Note : The system can kill your program without calling onDestroy() after onStop() has been called. Therefore, any cleanup/data persistence code should be in either onPause() or onStop().
I have an app, a single activity app with fragments in it.
The usual use case for this app is, that you start it and put the phone away and every now and then, you get back to the phone and insert some data... It's a logging app, you are doing something and insert your results into the app...
I have the problem, that every now and then, my activity get's destroyed and is recreated with an empty bundle... (Most of the time this is not the case, but every now and then this happens...). My app sometimes starts a service, even this service is killed in this case...
This means, that the system has killed my app, does it? How can I avoid this?
I need to keep the user data and the current top fragments... And they are saved to the bundle and everything works as long as their states and the data get saved...
Btw., my activity is always the TOP ACTIVITY, only that the screen turns off often... I just want to keep my activity alive as long as possible until the user leaves it with the back button... Or to save the state reliably
IMPORTANT NOTE
onSaveInstance does not always work (it's not part of the lifecycle and therefore not guaranteed to be called)... it only works most of the time... I need a way to that works always... If android kills my app...
don't keep your app in memory
You don't want to block Android from killing your app. What you want is to restore your app's state properly. Then the user will never notice the app has been destroyed and the user still gets the benefit of an app that was destroyed when not in use.
If you really want this use a wakelock. This will drain your users battery so I think twice before implementing this... Info at How do I prevent an Android device from going to sleep programmatically?
onSaveInstanceState explained
To do so check what information is needed in the bundle and persist that information with the onSaveInstanceState(bundle:Bundle) method so you can reuse it in onCreate(sameBundle:Bundle).
More information available from Google documentation at Save your Activity state and Restore your Activity State.
About Android Activity lifecycle
As stated by #prom85 in the comments below it's not guaranteed that the onSaveInstanceState method will be called because it's not part of the lifecycle. Workaround for this is using the onPause lifecycle hook to ensure your data is stored.
More information at Android: onSaveInstanceState not being called from activity
I had a similar problem, I arrived at this post while searching for a solution, you have to play with the manifest to achieve this and also understand what exactly activity is, in Android eco system,
In Android activity is a task which has a pre defined work.
I dig a lot in the documentation, I found that, we can configure activity in two ways,
Persistent
non persistent
if you mention for the activity in the manifest as
android:persistent="true"
and run the below use case
Start the APP
Press back or home button
you select the activity in the back stack again to bring it to front
Activity enters start -> pause -> stop - > resume , it does not get into onDestroy method.
if do not mention
android:persistent="true"
for the same use case
Activity enters start -> pause -> stop -> destroy, and if you select the activity from the back stack
Activity enters resume->create->start
If you want to run a service/task on activity start which keeps running when the app is in back stack, then you have to start that in the onCreate method, and kill them onDestroy by specifying your activity as persistent in manifest.
I hope my above solution might help others who arrive here for the same problem
Hi I'm wondering how Android is managing memory and I can't find precise answer anywhere.
Let's assume I have an application with 5 activities on current activity stack (4 are stopped and 1 is resumed), there is no service connected. I press HOME button so that all of my activities are stopped.
I start some other memory consuming application and overall device memory is starting to be low. And the question is
... What will happen to my application?
Can system destroy only one or some of my activities to recover memory?
Will system kill the whole process of my application? Will all activities be nicely destroyed?
What will happen when I get back to my application when it was totally killed? Will it start from beggining (like the first start) or will it try to recover activities to previeous state / if yes - is it only the one on the top of the stack or all of them?
UPDATE:
Before asking this question I've seen Activity lifecycle a few times but it doesn't have answers to my questions.
I made some tests and I have some answers. "Stop process" in DDMS was a clue for testing.
I haven't tested answer for question 1, but as guide says:
If an activity is paused or stopped, the system can drop the activity
from memory by either asking it to finish, or simply killing its
process.
It seems that one or more of the activities can be destroyed gently(with onDestroy method) without killing the process. You will simply get (onCreate + bundle) when getting back to them.
Question 2 answer:
YES. Generally system kills the whole process this means all data including activities and static fields are destroyed. This is NOT done nicely - you won't get onDestroy or finialize() for any of your paused/stopped activities. This is why saveInstanceState() is called just before onPause method. onPause is basically the last method where you should save something because after this method you could never see onStop or onDestroy. System can just kill the process destroying all of your objects whatever they hold and whatever they are doing.
Question 3 answer:
What will happen when you get back to a killed application?
Prior to Android 2.2 - application will start from the beggining, with launcher activity.
Starting from 2.2 - system will restore the previous application state. What does it mean? It means that last visible activity will be recreated (onCreate + bundle). What will happen with activity stack? Stack is fine but all activities on it are dead. Each of them will be recreated (onCreate + bundle) when you get back to it with back button.
There is one more thing about that:
Normally, the system clears a task (removes all activities from the
stack above the root activity) in certain situations when the user
re-selects that task from the home screen. Typically, this is done if
the user hasn't visited the task for a certain amount of time, such as
30 minutes.
Conclusion?
Don't think that handling activity rotation problems can be solved
by android:configChanges="orientation". When you do that you will
get many other problems that you are not even aware of.
Test your application with DDMS - Stop process button. See This
Be careful when using static variables. Don't think that when you initialized them in activity 1 - you will have them initialized in activity 2. The only safe place to initialize global statics would be Application class.
Remember that you may never see onStop or onDestroy. Close files/databases, stop downloaders in onPause. When you want app to do something in BG - use foreground Service.
That would be it ... Hope I helped with my essey :)
First please have a look at this:
onPause() Called when the system is about to start resuming a
previous activity. This is typically used to commit unsaved changes to
persistent data, stop animations and other things that may be
consuming CPU, etc. Implementations of this method must be very quick
because the next activity will not be resumed until this method
returns. Followed by either onResume() if the activity returns back to
the front, or onStop() if it becomes invisible to the user.
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.
So, when you press "HOME" button on your device, your current foreground activity is put onto onPause() then onStop(), the other 4 should remain onStop()
According to Google's Documents:
If an activity in the foreground of the screen (at the top of the stack), it is active or running.
If an activity has lost focus but is still visible (that is, a new non-full-sized or transparent activity has focus on top of your
activity), it is paused. A paused activity is completely alive (it
maintains all state and member information and remains attached to the
window manager), but can be killed by the system in extreme low memory
situations.
If an activity is completely obscured by another activity, it is stopped. It still retains all state and member information, however,
it is no longer visible to the user so its window is hidden and it
will often be killed by the system when memory is needed elsewhere.
If an activity is paused or stopped, the system can drop the activity from memory by either asking it to finish, or simply killing
its process. When it is displayed again to the user, it must be
completely restarted and restored to its previous state.
And, for the process lifecycle:
Process Lifecycle 3. A background activity (an activity that is not visible to the user and has been paused) is no longer critical, so
the system may safely kill its process to reclaim memory for other
foreground or visible processes. If its process needs to be killed,
when the user navigates back to the activity (making it visible on the
screen again), its onCreate(Bundle) method will be called with the
savedInstanceState it had previously supplied in
onSaveInstanceState(Bundle) so that it can restart itself in the same
state as the user last left it.
All the quotes above are come from: Android Developers Reference: Activity
It is confirmed that the system can destroy non-acitve activities and recycle memories when you launched some memory consuming applications. And you can implement like: isFinishing() in your activity and then using "kill" button in DDMS to detect which of your activities is being dropped by system. But I guess the system will destroy the oldest one first. However it is no point to keep other activities when the "Launch Activity" has been recycled.
UPDATE
Here's some opinions I found from here:
Stopped state
When an activity is not visible, but still in memory, we say it’s in a
stopped state. Stopped activity could be brought back to the front to
become a Running activity again. Or, it could be destroyed and removed
from memory.
The system keeps activities around in a stopped state because it is
likely that the user will still want to get back to those activities
some time soon, and restarting a stopped activity is far cheaper than
starting an activity from scratch. That is because we already have all
the objects loaded in memory and simply have to bring it all up to the
foreground.
Stopped activities can be removed from memory at any point.
Can system destroy only one or some of my activities to recover
memory?
Yes. Android kills activities which are running in the background when there is a need for memory. Killing one or all might depend on some conditions. For an instance paused or stopped can make android kill an activity or a process itself. Here under Activity Lifecycle you can get the below points. I recommend you to go through that page completely. It will definitely clear your doubts.
If an activity has lost focus but is still visible (that is, a new
non-full-sized or transparent activity has focus on top of your
activity), it is paused. A paused activity is completely alive (it
maintains all state and member information and remains attached to the
window manager), but can be killed by the system in extreme low memory
situations.
If an activity is completely obscured by another activity,
it is stopped. It still retains all state and member information,
however, it is no longer visible to the user so its window is hidden
and it will often be killed by the system when memory is needed
elsewhere.
If an activity is paused or stopped, the system can drop
the activity from memory by either asking it to finish, or simply
killing its process. When it is displayed again to the user, it must
be completely restarted and restored to its previous state.
Will system kill the whole process of my application? Will all
activities be nicely destroyed?
Activity pertains to an individual whereas process pertains to group of activities. Look at the third point above again it kills the process as mentioned.
What will happen when I get back to my application when it was totally
killed?
Its similar to restart . Again the third point will give you some answers like When it is displayed again to the user, it must be completely restarted and restored to its previous state
Get some more information about memory related stuffs here.
Edit:
All activities in an application runs in a single process. So when a process is killed all the activities no matter 5 or 10 will be killed i.e., restarted. Restart will cause your application to start from a beginning no saved states.