Reconsiling the lifecycle methods and back key - android

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.

Related

Android Activity Back Stack Navigation issue

I have researched numerous posts regarding Activity back stacks, as well as the Android Developer website, but still can't find a solution to a problem I'm having.
Scenario:
I have Activity A, I navigate to Actvity B, from A and then press the back button to go to Activity A again:
Actvity A --> Activity B --> Actvity A
Nothing out of the ordinary..
Problem
When I press the back button to go to from Activity B --> Activity A, Activity B is not destroyed straight away, as expected it goes into a pause state and this is where I have strange problem. If I want to return to Activity B from Activity A and IF Activity B is still in a pause state all its life cycle methods are called when use startActivity(B) from Activity A:
Activity B - onCreate() > onPause > onStop > onDestroy <-- why is this happening
At this point, to me it shouldn't exist anymore, and I can't explain why it went through all its lifecycle methods, rather than just the start initialisation lifecycle methods. The fall out from this strange behaviour is that the Activity is still visible on screen but doesn't populate a RecyclerView which in first initialisation did so as expected. At this point if I press back Activity B enters a pause state again.
If Activity B is in a pause state (Activity A is at top of stack) and the framework ends Activity B through lifecycle callbacks and I navigate to Activity B again from A it works as expected (RecyclerView is populated), basically a fresh instance always works fine.
All I can assume, when referring to the Activity Lifecycle diagram, is that Activity B enters a pause state, however is destroyed without calling onStop, onDestroy etc.. meaning any Activity clean up operations I have in those callbacks aren't happening?
Things I've Tried
Changing various Intent filters, and combinations, when starting Activity B:
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_SINGLE_TOP
Calling finish() when onBackPressed() is called in Activity B
Various other fingers crossed and hope changes, nothing seems to work.
Can anyone help please!
Ok, so I found the answer to the problem - not obvious at first, but now I understand what was happening.
The root cause of the problem was to do with 2 instances of the same Activity (Activity B) referencing the same Objects (Objects supplied from DI library).
Firstly when returning to Activity A from Activity B, Activity B was not immediately destroyed, and this causes a complication - this instance would never be reused, however still existed for a period of a few seconds. In this situation when using startActivity(B) from Activity A it would create a new instance and destroy the old (hence why I was seeing logging in both creation and activity ending callbacks), if it still existed. In this scenario both instances were sharing the same object, and this object "cleaned up" the Activity when destroyed. So the object (Presenter in this case) was being told by the old instance that it should clean up the Activity as its being destroyed, however this was not the case, because a new instance had been created.
The solution
Quite simple really, every time a new instance of Activity B was created, store in the Presenter a unique number (startId), and when Activity B called onDestroy() pass its current unique number, and check they match - if they don't match its not the latest instance, so do nothing. Very similar idea when you want to stop a Service, and check its the latest Activity calling the service from the startId.
Personally I don't know why Activities aren't destroyed straight away on pressing back, but thats the reason why this was happening.

Android back button behaviour

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().

Task, Back Button, and onSaveInstanceSate method

Hello I am just a little confused after reading these materials on Tasks and Back Stack, Android Developer Guide:
It says:
When Activity A starts Activity B, Activity A is stopped, but the system retains its state (such as scroll position and text entered into forms). If the user presses the Back button while in Activity B, Activity A resumes with its state restored.
While in the APIs reference for onSaveInstanceState() method, it says:
One example of when onPause() and onStop() is called and not this method is when a user navigates back from activity B to activity A: there is no need to call onSaveInstanceState(Bundle) on B because that particular instance will never be restored, so the system avoids calling it.
The above two situations seem identical to me ("press the Back button to Activity A" and "navigate back from Activity B to Activity A"). But I don't understand why while the former says Activity A resumes with its previous state restored while the latter says the particular instance of Activity B will never be restored. Any explanations?
Thanks in advance!
I think the first one is saying that A will be saved so it can be restored, and the second one is saying that B will not be saved because it can't be restored.

Android - Tell if parent activity has been destroyed

So, I have written an app that has a Main activity (A), and various other sub-activities that all do something, report the work back to main, and finish.
What I am running into is that if the user leaves my app at Screens B or C, when they come back at a later time and dalvik has destroyed my activities for more RAM... the app starts back at B or C, and reads all the initialization stuff from the saved intent, and continues on as if nothing happened. Until they return back to activity A, where we get a force close from unexpected things.
I've twiddled with overriding onStop() and calling finish, but i think this is a bit scorched earth, I'd like to let them leave on that activity and come back. But i'd also like to detect if the underlying main activity has been destroyed, and then destroy my entire activity stack.
From reading around, I get the idea that onDestroy() is not always called, so it isnt reliable for me to insert some logic into Activity A's onDestroy.... Any ideas?
Try starting your sub activities B and C with the flag FLAG_ACTIVITY_NO_HISTORY.

Did back key destroy an activity?

I have an activity defined as below:
<activity android:name="com.example.ui.HomeActivity"
android:alwaysRetainTaskState="true"/>
A strange thing is that, when running on emulator, and the back key is pressed, the activity was destroyed (I saw onDestroy() called in log). But when running on my Nexus One phone, and the back key is pressed, the activity is not destroyed (I didn't see onDestroy() called in log).
Could someone tell me why?
Thanks.
When activity is in the background (after pressing Back key) it is always stopped but System can also decide to destroy it (eg. when system resources are low). You can't determine when it will be destroyed.
Activity can also be destroyed by calling finish(). You can determine that by checking isFinishing() status in onPause or onStop callback.
Do not count on onDestroy callback. If system will kill activity it wont be called.
By default, pressing the BACK key finishes (destroys) the current activity and displays the previous activity to the user.
source

Categories

Resources