Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android singleTask activity not as the root?

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.

like image 458
Tomask Avatar asked Nov 26 '15 16:11

Tomask


Video Answer


1 Answers

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.

like image 125
David Wasser Avatar answered Oct 11 '22 20:10

David Wasser