4

In the official online Android guide on tasks and back stack, there's a piece of information i find self-contradicting. So i'd be grateful if somebody could help me figure it out.

First off, there's the following statement:

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.

And then the singleTask launch mode is described, there's the following statement:

The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent() method, rather than creating a new instance.

Well, if i understand this correctly, the singleTask activities can only be the roots of their tasks, since they are created that way and the activities never trade places in the back stack. But how would such an activity react on receiving that call to its onNewIntent() method?

There's another remark about this matter on that page:

As another example, the Android Browser application declares that the web browser activity should always open in its own task—by specifying the singleTask launch mode in the element. This means that if your application issues an intent to open the Android Browser, its activity is not placed in the same task as your application. Instead, either a new task starts for the Browser or, if the Browser already has a task running in the background, that task is brought forward to handle the new intent.

So, the guide states that invoking a singleTask activity somehow brings it forward. But how can it be true if that activity is not on top of its task? Is the activity resumed, or it simply receives a call to its onNewIntent() method without being displayed to the user? I really don't understand.

PS: An almost identical question had already been asked more than a year ago, but there was no proper answer given to it. So while technically my question is a duplicate, i feel an urge to re-ask it since it really deserves a clear and unambiguous answer.

Semisonic
  • 1,152
  • 8
  • 21

1 Answers1

3

I will try to answer your question(s).

Firstly,

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.

This is actually wrong. Normally, activties in the stack are never rearranged, but you can bring an existing Activity to the front from somwehere else in the stack using Intent.FLAG_ACTIVITY_REORDER_TO_FRONT. For example, your activity stack looks like this: A->B->C->D where A is the root activity (at the bottom of the stack) and D is the topmost activity that is in the foreground (being shown). If D now does this:

Intent intent = new Intent(this, B.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);

This will move the existing instance of activity B to the front of the task so that it will not be shown on screen. The activity stack will now look like this: A->C->D->B.

Next you asked this:

The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent() method, rather than creating a new instance.

Well, if i understand this correctly, the singleTask activities can only be the roots of their tasks, since they are created that way and the activities never trade places in the back stack. But how would such an activity react on receiving that call to its onNewIntent() method?

In general, a singleTask activity is the root of its task. If there is already an existing task with a singleTask activity active in it, and you launch such an activity using startActivity(), then that task will be brought forward (so that it shows on screen) and onNewIntent() will be called on the existing instance of that activity. However, if the singleTask activity has started other activities in its task, all of those other activities will be finished (ie: the task is stripped back to its root Activity) BEFORE onNewIntent() is called on the existing instance of the singleTask activity.

There are cases where a singleTask activity is not the root of its task and then all bets are off (ie: the behaviour is not as documented). This can happen if the singleTask activity has the same taskAffinity as other activities in the app that are already active in a task. In that case, Android ignores the singleTask launch mode and treats the activity as if it has standard launch mode instead.

David Wasser
  • 93,459
  • 16
  • 209
  • 274