I have a series of activities in my application which starts with Activity "A" and followed by "B", "C" , "D" and "E". Activity "A","B","C" and "D" are transparent activities (transparent theme) while "E" is opaque.
The requirement is the Activity "A" should not be finished. I read through a blog http://www.skill-guru.com/blog/2011/01/13/android-activity-life-cycle/ which states that
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.
If an activity is completely obscured by another activity, it is
stopped.
The onStop() of Activity "A" is not called till the user browses to Activity "D" however it is called when Activity "E" is invoked.
Is there anyway that we can keep the Activity "A" running in the Activity stack? Is it a good solution to keep a static reference of the Activity in a Application object so that framework does not kill it ? What precautions can i take so that "A" is not killed? Is there a way that i can get a notification if this gets killed by framework so that i can recreate it ?
The requirement is the Activity "A" should not be finished.
An activity is finished via a call to finish(). This normally happens when the user presses the BACK button.
The onStop() of Activity "A" is not called till the user browses to Activity "D" however it is called when Activity "E" is invoked.
Correct.
Is there anyway that we can keep the Activity "A" running in the Activity stack?
It is "running" in the activity stack (for any reasonable definition of "running"), until such time as you call finish(), the user presses BACK, or the process is terminated. onStop() has no impact on that.
Is it a good solution to keep a static reference of the Activity in a Application object so that framework does not kill it ?
No, because it is not going to help. The activity will remain in memory until such time as you call finish(), the user presses BACK, or the process is terminated.
What precautions can i take so that "A" is not killed?
Do not call finish().
Is there a way that i can get a notification if this gets killed by framework so that i can recreate it ?
Your activity will be called with onDestroy() if it is finished. This may or may not occur if the process is terminated, depending on what triggered the termination and the state of the system at that time.
Related
(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.
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.
In Andoid Acitivity life cycle, why does an activity go through onPause() before going to onStopped()? Why can't the state go directly to onStopped()?
Paused and stopped are related but different states. From the point of view of the user, a paused activity cannot be interacted with, but may still be visible (e.g. if it has called a different Activity as a dialog). A stopped activity is guaranteed to be not visible at all (the uses is in another Activity or even a different app).
Of course, stopped implies paused, but the reverse is not the case.
From the official documentation.
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.
An even more detailed explanation is given in the Managing the Activity Lifecycle article in the Training section of the Android Developers site.
Refer to the documentation on Activities:
http://developer.android.com/reference/android/app/Activity.html
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."
Note: I would say "resuming another activity" instead of "resuming a previeous activity".
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."
Because the documentation says so :-)
And it makes sense. The app is open and the user pressed the home button: onPause() gets called. After a while the system needs the memory and closes the app: onStop() gets called.
Because, onPaused() is executed when your App is rotated or a Dialog is open.
onStop() when your App is not in the screen, so is necesary that this two points in the lifecycle to the user or programmer can identify what action is executed.
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
The main activity in my app sometimes calls startActivityForResult, expecting a result that will tell it (the main activity) what information to display next. Looking at the documentation for the process lifecycle, it appears that while the selection activity is active, the main activity is considered a "background" activity and could possibly be killed.
So what happens when the selection activity completes? I see that my activity will be re-created and onCreate is called with the SaveInstance Bundle, but then what? Is onActivityResult then called just as if my main activity had never exited and been re-created?
Also, is there any way to force this behavior in a testing environment, since it should otherwise be a very rare occurrence?
Hint: log statements
The paused state as described in docs is:
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.
That means, under normal circumstances , your main activity should just transfer the control to onActivityResult() when the selection activity completes.
However, docs also state that:
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.
In such cases, the main activity can be redrawn.
One important point to note is that the docs have never mentioned onActivityResult() as one of their lifecycle methods here
So, it might also be the case where android system treats a sub activity and parent activity (read startActivityforResult() and onActivityResult()) in the same manner as it treats an activity - dialog as stated here:
A visible activity (an activity that is visible to the user but not in
the foreground, such as one sitting behind a foreground dialog) is
considered extremely important and will not be killed unless that is
required to keep the foreground activity running.
The answer is basically "yes": The activity is recreated and the control flows through onCreate(), onActivityResult(), onStart(), and so on.
An activity is also destroyed if the user rotates the device, e.g. from portrait to landscape, unless the application did not explicitly prevent this behavior. So simply rotate the device (CTRL-F11 on the emulator) to test.
Suppose there are two activities A and B and Activity A calls Activity B through startOnActivityResult(intent,200) then your Activity goes to background and Activity B is called (onCreate,onStart,onResume) depends on what you have overridden.
Whenever your B activity calls finish() then your Activity B is destroyed and Activity A comes to foreground. In this case now ie Activity A the call will be onActivityResult -> onStart -> onResume but your onCreate will not be called as it is only called when you call a certain Activity.
Suppose you have not called finish() from activity B and called Activity A through intent then only you onCreate() will be called.
Also onActivityResult() is very useful when you want to retain value of your spinners or you want to notifydatasetchanged() your ListView of your First activity after the event of Third activity. You just have to check your resultCode from the Activities in onActivityResult and perform your actions