Let's say we have a default, empty activity with default behaviour, launched with default intent flags. User presses back button on the device. The activity disappear... but how, actually?
Is pressing back button behaving the same way like finish()?
Is the activity immedietely destroyed (onDestroy is called)?
Is the activity guaranteed to be destroyed, but not immedietely?
Is there any chance the activity won't be destroyed and this instance will be reused when this activity is launched in the future? (so only onPause and onStop -> onStart and onResume are called?)
I'm looking for a reliable answer, so please do not answer if you are not absolutely sure what happens here.
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
This is a subchapter from the official Android documentation that addresses your question. It is a subchapter of the topic Managing the Activity Lifecycle, which can be read here:
http://developer.android.com/training/basics/activity-lifecycle/index.html
It is definitely worth reading the whole chapter to get to know the details about Androids Activity behaviour. But the subchapter ( first link ) is the relevant part to this question.
you use should look into this try this
and please tell specific what you wish to do with back button for your default activities ......
When you press back, (if not intercepted by anything like the keyboard, fragment, activity, etc) the OS (via ActivityManager probably) will try to show the user the previous activity in your current task (again, ignoring fragments' back stack).
If there is no such activity, the task will be terminated and you'll go to the previous task - the home screen most of the times or some other application that might have launched your app.
You'll get onDestroy called soon (it depends on how long it takes to start the next activity but on a good phone it should be under 100-200ms).
Your activity instance won't be reused after onFinish. This happens before the activity is destroyed so if you need another activity of the same type, the OS will create another instance.
When the user presses the BACK key, the current activity is popped from the top of the stack (the activity is guaranteed to be destroyed, but not immediately, may be when the system resources are low) and the previous activity resumes (the previous state of its UI is restored).
Which actions does the back button/back key on Android trigger?
Definitly onDestroy() is called .....There are a few scenarios in which your activity is destroyed due to normal app behavior, such as when the user presses the Back button or your activity signals its own destruction by calling finish().
Related
I know that in Android, if stuff is idle for a while, the operating system will devour things to free up memory.
So if I have a first Activity, and I invoke a second Activity by using an Intent, and then invoke a third Activity using yet another Intent, I can use the back button to go back to the previous Activities.
But let's say I stay on the third Activity, and let the phone idle for a while until the OS decides to devour my app for memory. If I open the app again, will I have lost the stack I have formed from my Intents? Will I still be in the third Activity with the ability to press Back and go to Activity 2, then Activity 1?
The OS will handle how long a particular Activity stays "active" in memory. However, the "stack" shouldn't change, regardless of whether an activity is "active" or not. This is where the Bundle comes in handy and the methods: "onSaveInstanceState()" and "onRestoreInstanceState()".
Implementing these methods properly is the difference of the activity reappearing on the screen in an empty state vs. with its previous state maintained.
Some documentation on Recreating an Activity
The backstack stays intact for the task in hand. It will always stay in task and whenever the user presses the back button, it will go through the back stack like popping the last item. However, not all the activities in the stack are in the foreground. Usually, only the last item put into the back stack (the top of the stack) is in the foreground and if there are multiple apps/tasks open this may not even be true. Here is a great diagram to show this.
Now, lets say a user opens a task with a couple of activities in its back stack. The top activity is in the foreground and is running normally, but to preserve memory the other activities were destroyed. So now when the user presses the back button, the task knows what activity was in the back stack and knows it is now destroyed. So, it will recreate it following the Activities lifecycle and any data that was in it will be lost. One way to preserve it (mentioned by original answer) is using the onSaveInstanceState() and onRestoreInstanceState(), which save things in a bundle that Android preserves for the user so data can be saved. All of this information can be found in the docs. To answer your question more clearly, yes you will be in the activity you think you would be in, but you can treat it as a new instance of that activity and to recover the data from before to display it in the same way, you should use bundle and implement the methods aforementioned.
I create a child activity "B" from activity "A". if the user should leave the app for any reason (most likely hitting the home button), I would like activity "B" to end and the app to be at activity "A" once the user resumes.
If I call finish() manually, activity B ends and it returns to activity A. This is the behaviour I would like to happen when the user leaves the app.
I have tried to call finish() in the onPause(), onStop() and in the onUserLeavingHint() of activity B. In each case, this appears to work correctly, and I can see mParent.finishFromChild(this); being called inside activity B.
However, as soon as the user switches back to the app, the onCreate() of activity B gets called and the user ends up in activity B.
How can I ensure I end up in the parent activity when I call finish() from within an onStop() (or similar) handler?
UPDATE: It appears that the issue is related to activity B being declared as using a SingleInstance launch mode. Removing this feature seems to have resolved the issue. Changing this has introduced other issues that I have since managed to fix.
The reason for this happening is that Activity B is set as a SingleInstance Launch Mode. The reason it was set to this (by another developer) is somewhat related to the reason I had wished the activity was ended when the app is in the background - it was to ensure the user could not reach this activity by hitting back on any other activities subsequently dispatched from Activity B.
To resolve this. I first ensured no activities could be created from B. To instead return from B and pass any required Intents on to A. Simplifying the back stack. (Calling activity B with startActivityForResult() is one possible way of doing this.)
Now, the reason SingleInstance causes this issue to arise in this scenario, is because Activity B is launched in a seperate new task. When the user attempts to resume, they re-enter this single-activity task. The rest of the app is running in a seperate task. The only thing the task can reasonably be expected to do is relaunch the activity. When the user presses back, the only thing it can do from there is to close the task (and hence appear to exit the app). For the expected behaviour to occur the user would have had to have selected the other, first task (through a long click of the task list).
Hopefully this self-answer can help someone who has encountered a similar issue.
In answering a question here on SO about when onDestroy is called what appears to be an inconsistency in the Android docs arose.
According to the android docs regarding the task and backstack
"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). "
However at the same time, the android lifecycle suggests that activities are not automatically destroyed but rather paused if the UI is partially hidden, stopped if the UI is totally hidden, and destroyed only if the system is low on resources.
These are two opposite positions. So my questions is - which is it?
Shout out to #Raghunandan for going back and forth with me in comments for a while. Hopefully we will get an answer.
They are both correct in their context. Maybe the lifecycle should say "destroyed only if system is low on resources OR it is popped form the stack".
Consider this for example. You start with activity A, then start activity B from A, then start activity C from B.
Now both A and B are paused and stopped, but not destroyed.
If C is heavy on resources, A or B may be destroyed.
Now press Back button from Activity C, you are back to Activity B
Activity C is paused, stopped and destroyed .
Now press Back button again, you are back to Activity A
Activity B is paused, stopped, and destroyed
System tries to keep all the activity instances so they can be re-opened quickly. But when an activity is popped from the stack, there is no way for user to re-open them in future, at least not the same instance.
There is no contradiction in these two statements.
onDestroy is called when you press BACK unless you override onBackPressed not to call finish() or do a strange thing of overriding finish and not calling super.finish().
If you don't stop the call to Activity.finish, onDestroy is always called.
The other statement speaks nothing about pressing BACK and I can find nowhere under the link you have provided here that
and destroyed only if the system is low on resources.
Additinally to onDestroy being called when app is low on resources (which strangely doesn't happen on my phone; I get OOM) it is called when 20 other Activities globally (from all applications) are started after this one.
I also encouarge you to check out yet another answer on when onDestroy is called again for a real reason of onDestroy not being called.
I am really confused. I have read that the back button
calls onDestroy()
can close up your currently-running activity
calls onPause()
I think onPause() should be right. But this is an side effect, because the Activity gets into the background. I found nothing in the docs. But maybe I have overlooked something.
Can someone please explain to me what the back button is supposed to do programmatically? Some references would also be nice. :-)
I have read that the back button calls onDestroy(), can close up your currently-running activity, calls onPause()
All three are correct.
I found nothing in the docs.
Quoting the Android documentation:
When the user presses the BACK key, 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).
To elaborate, if there is nothing else that will consume the BACK button press (e.g., an open options menu), your Activity will be called with onBackPressed(). The default implementation of this calls finish(). This will take your activity from the running to the destroyed states, calling onPause(), onStop(), and onDestroy() in sequence, as shown in the event flow diagram:
Just to add, browser application overrides onBackPressed() to go back to previously opened tabs (if available) and it not, closes the application.
Is there any way to tell Android, "If the user exits this Activity by hitting the 'home' key, immediately finish() every Activity on the stack that has ever been associated with this Application?" Or, alternatively, a way for an Activity whose onPause() method has been forcibly called by a user hitting 'home' to finish() not only itself, but the Activity that started it as well?
The problem I have is workflow. My application's users basically go back and forth between a main Activity and "detail" Activity windows. They see something in the main Activity, tap it, the child detail Activity gets spawned, they use it for a while, then hit back to return to the main Activity. I can't finish() the main Activity after starting the child Activity, because then the back button would quit working. The problem is that now, if the user exits by hitting the home key in a child Activity, it leaves behind a zombie parent Activity. If the user relaunches the application, uses it for a while, then explicitly triggers a shutdown by hitting menu->quit from the main Activity (where I kill the service, then call finish()), the Activity goes away, and the user gets dumped into the zombie Activity from the previous run (which promptly crashes if the user tries to do anything, because the background service it depends on has already been shut down, and all the BroadcastReceivers that would have otherwise been listening have been removed, so its cries for help go unheard).
I'm actually kind of puzzled, because I already have android:launchMode="singleTask" sitting in the manifest tag for my launch activity, and I thought launchMode="singleTask" was explicitly supposed to prevent things like this from happening by making sure that any lingering Activities from a previous run were safely dead before it relaunched.
The easiest way of doing this is:
Intent i =new Intent(CurrentClass.this,HomeClass.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
Perhaps you can mark all the Activities in the stack with clearTaskOnLaunch (see http://developer.android.com/guide/topics/manifest/activity-element.html#clear).You can mark all the Activities that would be in the task with the attribute.