I read the developers guide on android.com about Task and back stacks where it says:
Suppose, for example, that the current task (Task A) has three
activities in its stack—two under the current activity. The user
presses the HOME key, then starts a new application from the
application launcher. When the Home screen appears, Task A goes into
the background. When the new application starts, the system starts a
task for that application (Task B) with its own stack of activities.
After interacting with that application, the user returns Home again
and selects the application that originally started Task A. Now, Task
A comes to the foreground—all three activities in its stack are intact
and the activity at the top of the stack resumes.
It seems like every Task creates it own stack (back stack). Is my assumption is real or there's only one stack, usually a compiler has, like C?
The back stack can cross Task boundaries. When the launchmode for an activity is set to singleTask, the activity will be created in a new task.
Suppose activity B has launchmode=singleTask in the XML file. When activity A launches activity B, the latter will be in its own task. However, pressing the back key will bring the user back to activity A. So A and B are in the same back stack, but are in different tasks.
See the discussion of launchmode in the page http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html.
disclaimer: I have not verified if the documentation is correct.
I'd say that what they say is true! Every Task creates it own stack (back stack).
Related
This is a documented behavior on Android:
Consider for example, the following task flow for a current task (Task
A) that has three activities in its stack, including two under the
current activity:
The user uses the Home button or gesture, then starts a new app from the app launcher.
When the Home screen appears, Task A goes into the background. When the new app starts, the
system starts a task for that app (Task B) with its own stack of activities.
After interacting with that app, the user returns Home again and selects the app that
originally started Task A. Now, Task A comes to the foreground—all three activities in its
stack are intact and the activity at the top of the stack resumes. At
this point, the user can also switch back to Task B by going Home and
selecting the app icon that started that task (or by selecting the
app's task from the Recents screen).
So this is the scenario where there already exists a task for the App and the user taps on the launcher icon, the task is brought to foreground. As you can contemplate that there is an Intent required to launch activities.
QUESTION: What flags are responsible for resuming the task(top Activity of the task) rather than creating a new instance of the Activity?
Note: If you are thinking FLAG_ACTIVITY_NEW_TASK then that is supposed to clear out all the activities in the task first and then deliver the Intent to the launcher activity which would be the root activity in the task(through onNewIntent()) but that is not what's happening.
You can use launch mode in the manifest. Something like this.
<activity android:name="com.smart.review.BaseActivity" android:launchMode="singleInstance"/>
I've been reading doc regarding to launch modes and there is one thing I don't understard. The doc says that singleTask activity is always the root of the stack:
In contrast, "singleTask" and "singleInstance" activities can only
begin a task. They are always at the root of the activity stack.
Moreover, the device can hold only one instance of the activity at a
time — only one such task.
But: if you look at this part of doc at Figure 4, you see that when Activity 2 starts Activity Y (puts that task to foreground), Activity Y was already on the top of the task and will be on the top of the current task, not the root.
I tried this scenario in this simulation app and when I create singleTask activity, it always creates a new task. However, if the only instance already exists, it finishes all activities above this one so the only instance can be the root (and also the only activity in the task).
How could the Activity Y become on the top of the task above the Activity X?
Is there any other reason I'm missing?
PS: I also don't really understand the difference between Task and back stack.
As usual (sigh), the documentation is wrong. In the diagram you referenced, obviously Activity Y can't be defined as singleTask and yet be the top activity in a background task containing 2 activities.
When testing scenarios with special launch modes singleTask and singleInstance, please be aware that taskAffinity plays an important role in this behaviour, as taskAffinity takes priority over special launch modes.
Regarding the difference between "task" and "back stack":
A "task" is a stack of activities that can be manipulated as a whole group.
When you launch an application (assuming that it isn't currently running), Android creates a new task which is in the foreground and contains the root activity of the application you launched.
When that activity starts new activities, these new activities are added to current task (usually, although there are exceptions to this behaviour).
When you press the HOME button, the current task is moved from the foreground to the background.
When you show the list of "recents", what is displayed is the list of recent tasks, not the list of recent activities or list of recent applications.
When you select a task from the list of recent tasks, if that task is still active (still has live activities in it), the entire task (including all of its activities) will be brought from the background to the foreground.
Tasks can also be "stacked". When an activity in the current task starts an activity in a new task, the new task is stacked on top of the current task. This only serves to control what happens when the new task completes. In the usual case, when the new task completes (all of its activities have finished), Android will return the user to the previous task (ie: the task that started the completing task).
A "back stack" usually refers to a set of activities within a task. Each task has its own stack of activities. This is used to control what happens when the current activity (the one on top of the back stack) finishes. Normally Android returns the user to the activity that is directly underneath (below) the finishing activity in the back stack.
The Android code and documentation often refer to the "root" of a task (this is the activity that was used to start the task) and the "top" or "front" of a task (this is the activity that is currently being shown).
Actually, the documentation lies :-( Here's an example:
In contrast, "singleTask" and "singleInstance" activities can only
begin a task.
This statement is usually, but not always correct. For example, let's say I have 2 activities: A and B. A is the launch activity (ie: the one with ACTION=MAIN and CATEGORY=DEFAULT) and is defined with standard launch mode. B is defined with launchMode="singleTask". I start the application and Android creates an instance of A. In A I then do:
startActivity(new Intent(this, B.class));
This will create a new instance of activity B and put it on top of A in the same task. It will not create a new task with activity B as the root. The reason is that activity A and activity B have the same taskAffinity (by default all activities of an application have the same taskAffinity), and Android will ignore the launch mode of B in this case.
The documentation also says:
Moreover, the device can hold only one instance of the activity at a
time — only one such task.
Again, taskAffinity can break this behaviour. Assume again we have A, B and C, all with the same (default) taskAffinity. A and C have standard launch mode, B has launchMode="singleTask". If A starts B, the instance of B ends up not in a new task, but in the same task as A (see above). Now B starts C. Android creates an instance of C and puts it on top of B in the same task. Now C calls:
startActivity(new Intent(this, B.class));
Android creates a new instance of B and puts this on top of C in the task. There are now 2 instances of B and neither of them is the root activity of the task! This behaviour is also due to the fact that taskAffinity trumps launch mode.
I am new to Android Programming.
I want to understand how Activity Stack is maintained for a particular Android Application and how does it changes based on user navigation.
For example, if there are multiple activities then how Activity Stack behaves when user clicks on Back Button or Home Button or launches a new Activity?
I was trying to find a suitable post where I can get all the information, but I did not get any. Can somebody please suggest me some links/posts where I can learn this?
Thanks!
Edited:
Links/Posts that I came across so far:
onSaveInstanceState is not saving my values ( onCreate input Bundle is always null )
Saving Android Activity state using Save Instance State
Android: Launch mode 'single instance'
Do you mean activities and the back stack?
Here is a link:
http://developer.android.com/guide/components/tasks-and-back-stack.html
A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (the back stack), in the order in which each activity is opened.
The device Home screen is the starting place for most tasks. When the user touches an icon in the application launcher (or a shortcut on the Home screen), that application's task comes to the foreground. If no task exists for the application (the application has not been used recently), then a new task is created and the "main" activity for that application opens as the root activity in the stack.
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). Activities in the stack are never rearranged, only pushed and popped from the stack—pushed onto the stack when started by the current activity and popped off when the user leaves it using the Back button. As such, the back stack operates as a "last in, first out" object structure. Figure 1 visualizes this behavior with a timeline showing the progress between activities along with the current back stack at each point in time.
I was going through the documentation for single instance and was trying out few samples.
In one of my sample I have three activities: A->B->C ,
where B has android:launchMode="singleInstance" in manifest. Activity A and C has default launch mode.
Scenario:
After navigating to C via A and B (i.e A->B->C), back button press from Activity C takes to Activity A (C->A), but back button press from Activity A does not quit the app, rather brings the Activity B to front, then back button press from Activity B quits the app.
Question
Why does Activity B comes to foreground when back button is pressed from Activity A?
Other scenario:
Similarliy, from Activity C if user presses device Home button, and come back the app by long home press, C stays in foreground. But back button press flow takes C-> A -> quits the app. This time Activity B does not come to foreground.
After navigating from A->B you have 2 tasks: The first one contains A, the second one contains B. B is on top and A is below that.
Now when navigating from B->C Android launches activity C into the task containing A (it cannot launch it into the task containing B because B is defined as "singleInstance", so it launches it into a task that has the same "taskAffinity", in this case the task containing A). To do that, Android brings the task containing A to the front. Now you have 2 tasks: The task containing A and C in the front, and the second one containing B below that.
Now you press the BACK key, which finishes activity C and returns to the activity below that in the task, namely A. You still have 2 tasks: The one containing A in the front, and the one containing B below that.
Now you press the BACK key again. This finishes activity A (and thereby finishes the task that held A) and brings the previous task in the task stack to the front, namely the task containing B. You now have 1 task: the task containing B.
In your other scenario, after navigating from A->B->C, you start with 2 tasks: The task containing A and C in the front, and the second one containing B below that.
Now you press the HOME button. You now say that you "come back to the app by long press". This isn't exactly correct. You can't "come back to the app". You can only "return to a task". But you've got 2 different tasks: If you do a long press you should see the 2 tasks. They probably have the same icon (unless you've provided a different icon for activity B) so you may not be able to tell them apart. If you select the task that contains A and C, then that task will be brought to the front with activity C on top. If you now press the BACK key, activity C will finish and the activity under it, activity A will be shown. If you now press the BACK key again, activity A will be finished and you will be returned to the HOME screen. The task containing B is still in the list of recent tasks, but it is no longer in the task stack under your other task because when you press the HOME button it is like going back to zero. You start all over again. You have no active tasks, so all tasks are in a row, they aren't in a stack and there is no hierarchy.
Also, in your question you use the phrase "quits the app". This also isn't quite correct. The only thing that a BACK button press does is to finish the current activity. If the current activity is the only activity in a task, it also finishes that task. However, it doesn't "quit the app". Especially in your case, since your "app" actually exists in 2 separate tasks.
Hopefully this is clear.
From the doc
"singleInstance" activities can only begin a task. They are always at the root of the activity stack. Moreover, the device can hold only one instance of the activity at a time — only one such task.
A "singleInstance" activity, on the other hand, permits no other activities to be part of its task. It's the only activity in the task. If it starts another activity, that activity is assigned to a different task
I have doubt with android backstack , please consider the scenario I have two activities A and B in same app ,
start with A.
from A launch B using FLAG_ACTIVITY_NEW_TASK
from B launch A using FLAG_ACTIVITY_NEW_TASK
press Back button 3 times to return to home screen.
My question is how does the backstack work with this flag , is new task created every time and previous task is pushed to background or activity is created on top of same task.
My doubt is if first one is correct then does back button really remove the activity from top of the stack and if second is correct what is the use of that flag in correct sense.
Thanks in advance.
Regards,
Rohit
First of all, launching B using FLAG_ACTIVITY_NEW_TASK will NOT create a new task unless you have explicitly set android:taskAffinity in the manifest for B. The reason for this is that, by default, all Activities in your application have the same taskAffinity and taskAffinity overrides FLAG_ACTIVITY_NEW_TASK.
If you have set the taskAffinity of A and/or B so that they are different (or both empty), then it works like this:
User launches A from homescreen. You now have one task (let's call it TaskX)
A launches B with FLAG_ACTIVITY_NEW_TASK. You now have two tasks (let's call the new task TaskY). TaskX is pushed to the background and TaskY is in the foreground.
B launches A with FLAG_ACTIVITY_NEW_TASK. You still only have two tasks. B (in TaskY) launched A which created a new instance of A and put it in TaskX because the first instance of A has the same taskAffinity as the second instance of A). This also causes TaskX to come to the foreground and TaskY to go to the background.
Press "back". The second instance of A is removed from the stack and you go back to the first instance of A in TaskX. Pressing the "back" key goes back within the current task.
Press "back". The first instance of A is removed from the stack. TaskX is now empty as it has no activities in it. The previous task (TaskY) is brought to the foreground and B is resumed.
Press "back". The instance of B is removed from the stack. TaskY is now empty and the home screen is shown.