具有singleTask启动模式的活动及其在后台堆栈中的位置

时间:2015-07-22 22:22:15

标签: android android-intent android-activity back-stack launchmode

在官方的在线Android guide on tasks and back stack中,有一条我发现自相矛盾的信息。如果有人能帮助我解决这个问题,我将不胜感激。

首先,有以下声明:

  

堆栈中的活动永远不会重新排列,只会在当前活动启动时从堆栈中推送并弹出到堆栈中,并在用户使用“返回”按钮离开时弹出。

然后描述 singleTask 启动模式,有以下声明:

  

系统创建新任务并在新任务的根目录下实例化活动。但是,如果活动的实例已存在于单独的任务中,则系统会通过调用其onNewIntent()方法将意图路由到现有实例,而不是创建新实例。

好吧,如果我理解正确的话, singleTask 活动只能是他们任务的根源,因为它们是以这种方式创建的,并且活动永远不会在后台堆栈中交换位置。但是这样的活动如何对接收对其 onNewIntent()方法的调用作出反应?

在该页面上有关于此事的另一个评论:

  

作为另一个例子,Android浏览器应用程序声明Web浏览器活动应始终在其自己的任务中打开 - 通过在元素中指定singleTask启动模式。这意味着,如果您的应用程序发出打开Android浏览器的意图,则其活动不会与您的应用程序放在同一任务中。相反,要么为浏览器启动新任务,要么如果浏览器已经在后台运行任务,则该任务将被提前处理新意图。

因此,该指南指出,调用 singleTask 活动会以某种方式使其前进。但是,如果这项活动不是最重要的,那怎么可能呢?活动是否已恢复,或者只是在没有向用户显示的情况下接收对其 onNewIntent()方法的调用?我真的不明白。

PS:一年多前已经问过几乎相同的question,但没有给出正确答案。因此,虽然从技术上来说,我的问题是重复的,但我觉得有必要重新提出它,因为它确实值得一个明确而明确的答案。

1 个答案:

答案 0 :(得分: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.