您的位置:首页 > 移动开发 > Android开发

Android-Tasks and Back Stack

2014-11-03 15:15 309 查看
转载请标明出处:/article/1908011.html

原文:http://developer.android.com/guide/components/tasks-and-back-stack.html

一个应用一般都会包含多个activity。每一个activity都是围绕着用户的特定功能来实现的,并且是可以被别的activity启动起来的。比如:邮件应用可能有一个activity用来展示新邮件列表。当用户选择了一个邮件以后,会启动一个新的activity来展示邮件内容。

activity甚至可以启动设备上的别的应用。比如:你的应用想发送邮件,那你就可以定义一个做发送操作的intent,这里面会包含一些数据比如收件人的地址还有消息。另一个应用的activity如果它声明了能够处理这种类型的intent就可以启动来响应。这种情况下,intent是用来发送邮件的,所以邮件应用程序就启动起来了。如果多个activity都支持同样的intent,系统会让用户选择使用哪一个应用。当邮件发出去以后,你的activity会resume,看起来邮件的activity就像是你自己的应用的一部分一样。虽然activity是来自不同的应用的,android系统通过把这些activity放在同一个task中无缝的保持了用户体验。

task是用户为了完成特定任务而操作的activity的集合。这些activity以他们打开的顺序放在一个堆栈(back stack)中。

home键是大多数task开始的地方。当用户点击应用程序launcher的icon的时候(或者是home屏的快捷方式),应用程序的task会被放到前台。如果应用不存在于任何的task中(应用最近一直都没有使用过),系统会创建一个新的task,然后打开应用的主activity,并把它作为task的back stack的根activity。

当前activity打开一个新activity的时候,新activity会被放到back stack的栈顶,并且获取焦点。前一个activity仍然还在stack中,但是是处于stop状态。当一个activity进入stop的时候,系统会保持它的用户界面的状态。当用户按下back按键的时候,当前的activity会从stack的栈顶弹出(activity被销毁),之前的activity会进入resume(它的UI的状态会重建)。

stack中的activity的顺序永远都不会改变,只有可能在栈顶做push和pop,当被当前的activity启动的时候做push,当用户按下back键离开的时候做pop。back stack是后进先出的数据结构。表1可视化的展示了这种行为,按时间先后展示了activity和当前back stack的状态。



图1. 展示了task中的一个activity是如何向back stack中添加新的元素。当用户按下back键的时候,当前的activity会被销毁,前一个activity会被唤醒。

如果用户继续按下back键,task中的activity会依次弹栈,并展示前一个activity,一直到用户返回到home为止(或者是到task开始的activity为止)。当所有的activity都被从stack中弹出以后,task就也不再存在了。

task是一个紧密结合的整体,当用户启动一个新的task或者是按下home键退回到home屏的时候,task可以整体被移到后台。当task在后台的时候,task中的所有的activity都是处于stop状态的,但是task的back stack仍然是完整的。task只是被别的task夺去了焦点而已,如图2所示。



图2.两个task:Task B在前台接收用户的交互,Task A在后台等待唤醒。

task是可以返回到前台的,这样用户就可以重新回到他们当初离开的地方。假如当前的task(Task A)在它的back stack中有3个activity,当前的activity下面还有两个activity。这时候,用户按下了home键,然后启动一个新的应用。当home屏出现的时候,Task A就进入了后台。当心应用启动起来的时候,系统会给这个应用启动一个新的task(Task B),而且它也是有自己的back stack的。当跟这个应用做了一些交互以后,用户再次返回到了home,然后选中了启动Task A的应用。现在Task
A变为前台了,back stack中的3个activity都是完整的,并且栈顶的activity会被唤醒。这时候,用户也可以再切换到Task B,只要返回到home然后选中启动Task B的那个应用的icon就可以(或者是在overview screen中选中应用所在的task)这就是android上的一个多task的例子。

注意:同时可以在后台有多个task。但是,如果用户同时在后台运行多个task,为了回收内存,系统可能会销毁掉一些后台的activity,这回导致某些activity的状态丢失。下面的章节会介绍Activity的状态。

因为back stack中的Activity的顺序是永远都不会改变的,如果你的应用允许用户从多个Activity中启动某一个特定的Activity,这个Activity的一个新的实例会被创建出来,然后被压到栈顶(而不是把stack中应经存在是实例移动到栈顶)这样,你应用中的一个Activity可能会被实例化多次,就像图3那样。如果用户用back键回退,Activity的实例(带有他们自己的UI状态)会按照压栈的顺序依次被弹栈。但是,如果你不想让你的Activity被实例化多次的话,你也可以修改这种行为。稍后的章节会介绍如何管理Task。

Activity和task的默认行为总结如下:

(1)

当Activity A启动起来Activity B以后,Activity A就会stop,但是系统会保存它的状态(比如滚动的位置,表单输入的文本)。如果用户在Activity B中按下back键,Activity A会被唤醒,然后重建状态。

(2)

当用户按下home键离开一个task之后,当前的Activity会被stop,然后被置后台。系统会保存task中所有的Activity的状态。如果用户选中了启动task的那个应用的icon,task又会被放到前台,然后唤醒task中栈顶的Activity。

(3)

如果用户按下了back键,当前的Activity会被从stack中弹出然后被销毁,前一个Activity会被唤醒。当Activity被销毁以后,系统不再保存Activity的状态。

(4)

Activity可以被实例化多次,甚至是在不同的task中。

导航设计

关于更多android上导航的工作原理,可以参考android设计的导航指南(http://developer.android.com/design/patterns/navigation.html)

如何保存Activity的状态

正如之前讨论的那样,当Activity被stop以后,系统默认会保存它的状态。当用户back到之前的Activity的时候,它的UI还是它离开时的样子。但是,你可以而且是应该使用系统回调来保存你的Activity的状态,以防你的Activity被销毁了必须要重新创建。

当系统stop掉你的一个Activity以后(比如启动了一个新的Activity或者整个task被放到了后台),如果需要回收内存的话,系统可能会把这个Activity销毁掉。当发生这种情况的时候,Activity的状态就会丢失掉,但是系统仍然知道在回退栈中有这么一个Activity。但是,当这个Activity被放到栈顶的时候,系统必须要重新创建这个Activity(而不是唤醒)。为了避免用户的工作,你应该通过实现onSaveInstanceState()这个回调来保存Activity的状态。

关于如何保存Activity的状态,参考Activity的文档(http://developer.android.com/guide/components/activities.html#SavingActivityState)。

管理Task

上面介绍的android管理task和back stack的方式(把连续启动的Activity按照后入先出的形式放到同一个task中)对大多数应用来说都可以很好地工作,因为你不需要担心你的Activity是如何跟task关联上的,也不用关心Activity在back stack中是如何存在的。但是你可能会想要改变这种行为。你可能想让你应用中的Activity在启动起来的时候开始一个新的task(而不是放到当前的task中),或者当启动Activity的时候,你想使用已经存在的一个实例(而不是在栈顶创建一个新实例),或者当用户离开task的时候,你想清空你的back
stack,只留下根Activity。

通过设置manifest的<activity>元素的属性,或者是通过设置传递到startActivity()的intent的flag,就可以做这样的事情甚至更多。

本文中,相关的<activity>的属性:

taskAffinity

launchMode

allowTaskReparenting

clearTaskOnLaunch

alwaysRetainTaskState

finishOnTaskLaunch

相关的flag:

FLAG_ACTIVITY_NEW_TASK

FLAG_ACTIVITY_CLEAR_TOP

FLAG_ACTIVITY_SINGLE_TOP

接下来的章节,你会看到如何使用这些属性和flag来定义Activity如何跟task关联还有Activity在back stack的行为。

关于task和Activity是如何在overview screen中展现和管理的将会被单独进行讨论,详细信息请参考:Overview Screen(http://developer.android.com/guide/components/recents.html)一般来说,你应该允许系统来定义你的task和Activity是如何在overview screen进行展示的,并且不需要来改变这种行为。注意:大多数应用都不应该改变Activity和task的默认行为。如果你决定让你的Activity改变默认的行为,必须要当心,要测试当启动或者按下back键从别的Activity导航到本Activity和task的时候确保Activity的可用性。尤其要测试那种可能跟用户预想的行为有冲突的那种导航行为。

定义启动模式launch mode

Launch mode允许你来定义一个新的Activity实例如何跟当前的task进行关联。

可以用下面两种方式来定义:

(1)使用manifest文件

当你在manifest文件中声明Activity的时候,可以指定当Activity启动的时候,如何跟task进行关联。

(2)使用Intent flags

当调用startActivity()的时候,可以在intent中包含一个flag,它就描述了新的Activity如何(是否)跟当前的task进行关联。

如果Activity A启动了Activity B,Activity B可以在manifest文件中定义它是如何跟当前的task进行关联的,Activity A也可以请求Activity B如何跟当前的task进行关联。如果这两个Activity都定义了Activity B跟当前task的关联方式,Activity A的请求(用intent来定义)会覆盖Activity B的请求(用manifest定义)。

注意:有些launch modes只对manifest文件可用,有些只对intent可用。

使用manifest文件

当在manifest文件中声明Activity的时候,可以使用<activity>元素的launchMode属性来制定Activity如何跟task相关联。launchMode属性指定了Activity如何被启动到一个task中,可以给launchMode属性设置4个不同的值。

"standard"

这是默认值。系统会在启动这个Activity的task中创建一个Activity的新实例,然后把intent传给它。Activity可以被实例化多次,不同的实例可以属于不同的task,一个task可以有多个实例。

"singleTop"

如果Activity的一个实例已经存在于当前task的栈顶,系统会调用这个实例的onNewIntent()并把intent传递给这个Activity,而不是创建一个Activity的新的实例。Activity可能会被创建多次,每一个实例都可以属于不同的task,一个task也可以有多个不同的实例(只要栈顶的Activity不是新创建的这个Activity就可以)

比如,假如说有一个task,它的back stack中有4个Activity,Activity A是跟Activity,然后一次是Activity B,C,D,Activity D是栈顶(栈里面是A-B-C-D)。这时候来了一个启动Activity D的intent,如果D是默认的launch mode,那么一个新的实例会被创建出来并压栈,栈就变成A-B-C-D-D。但是,如果D的launch mode是"singleTop",之前已经存在的那个D的实例会在onNewIntent()中接收到这个intent,因为D现在是在栈顶,然后栈里面还是A-B-C-D。但是,如果这时候来的是启动Activity
B的intent,一个新的Activity B的实例会被添加到stack中,虽然现在的launch mode是"singleTop"。

注意:当新的Activity实例被创建了以后,用户可以按下back键返回到之前的Activity。但是,当已经存在的Activity实例收到一个新的intent以后,在新的intent到达onNewIntent()之前,用户不能够按下back键返回到Activity之前的状态。

"singleTask"

系统会创建一个新的task,并且实例化一个Activity作为这个task的根Activity。但是,如果Activity有实例已经存在于另一个task中,系统会把intent发送到这个已经存在的实例上,然后调用它的onNewIntent()方法,而不是创建一个新的实例。同时只能存在Activity的一个实例。

注意:虽然Activity是以new task的方式启动的,但是按下back键仍然你可以回到之前的Activity。

"singleInstance"

与 ”singleTask”一样,但是系统不能启动别个 Activity到这个 Activity的实例所在的 task中去。这个 Activity总是单一的,且是他所在的 task的唯一成员。通过这个 Activity启动的其它任何 Activity都将单独启动一个单独的 task。

看另一个例子,android浏览器应用通过给<activity>元素指定singleTask模式声明了web浏览器的Activity总是在它自己的task中,这意味着,如果你的应用发起一个打开android浏览器的intent,它的Activity跟你应用是不再同一个task中的。相反,要么是给浏览器创建一个新的task,要么浏览器已经有一个在后台运行的task,这个后台task会被放到前台,然后处理这个新的intent。

不管新的Activity是不是跟启动它的Activity是在同一个task中,按下back键总能让用户返回到前一个Activity。但是,如果你使用singleTask模式启动了一个Activity,如果Activity有一个在后台task中的实例,整个后台task就会被放到前台。这时候,back stack会包含这个task中的所有的Activity,并且是在栈顶。图4说明了这种情况。



图4. 展示了"singleTask"启动起来的Activity是如何被加入到back stack的。如果Activity已经是后台task的一部分,那么整个的后台task的back stack也会变成前台,而且是在当前stack的栈顶。

想了解更多关于manifest文件中launch mode的信息,参考<activity>的文档,那里有跟多关于launchMode属性和可接受的值的讨论。

注意:用launchMode属性指定的Activity的行为是可以被用带有flag的intent启动的Activity所覆盖的。

使用Intent flag

当启动一个Activity的时候,可以通过给发送到startActivity()的intent添加flag来修改activity到task的默认关联方式。可以使用的修改默认行为的flag有:

FLAG_ACTIVITY_NEW_TASK

在一个新的task中启动Activity。如果你要启动的Activity已经存在于一个已经运行的task中,那么这个task就会被放到前台,并会重建task最后的状态,Activity会在onNewIntent()中收到新的intent。这和之前讨论的launchMode为"singleTask"的值的时候的行为是一样的。

FLAG_ACTIVITY_SINGLE_TOP

如果要启动的Activity就是当前的Activity(在back stack的栈顶),那么这个已经存在的实例会收到onNewIntent()调用,而不是创建一个新的Activity。这和之前讨论的launchMode为"singleTop"的值的时候的行为是一样的。

FLAG_ACTIVITY_CLEAR_TOP

如果要启动的Activity已经在当前的task中,那么位于这个Activity实例之上的所有的Activity都会被销毁掉,不是创建一个新的Activity实例,然后这个Activity会被唤醒,然后在onNewIntent()中收到intent。没有与之对应的launchMode的值。

FLAG_ACTIVITY_CLEAR_TOP经常跟FLAG_ACTIVITY_NEW_TASK一起使用。当一起使用的时候,这些flag可以用来定位到在其他的task中已经存在的Activity并把Activity放到一个能响应intent的位置上。

注意:如果Activity的launch mode是"standard",它也会被从stack中移除,然后一个新的Activity实例放到它的位置,并处理传进来的intent。这是因为当launch mode是"standard"的时候,总会给intent创建一个新的实例。

Handling affinity

affinity表明了Activity更喜欢属于哪一个task。默认情况下,同一个应用里面的Activity的affinity都是一样的。因此默认情况下,同一个应用里面的所有的Activity都喜欢在同一个task中。但是,你也可以修改Activity的默认的affinity。不同应用里面的Activity也可以共享一个affinity,同一个应用里面的Activity也可以有不同的affinity。

你可以修改<activity>元素的taskAffinity属性来修改指定activity的affinity。

taskAffinity属性接受string值,在<manifest>元素声明的默认包名中必须是唯一的,因为系统会使用这个名字来标识应用的默认task affinity。

affinity在两种情况下会有作用:

(1)当启动Activity的intent中包含了FLAG_ACTIVITY_NEW_TASK的时候。

默认情况下,一个新的Activity是通过调用startActivity()而被放到task中的。它会被放到跟调用者同一个task中。但是,如果intent中包含了FLAG_ACTIVITY_NEW_TASK,系统会给这个新的Activity查找一个不同的task。一般来说,会是一个新的task。但是,这不是必须的。如果已经存在一个跟这个新Activity有相同affinity的task的话,这个Activity会被放到这个task中。如果没有,就会被放到一个新的task中。

如果这个flag把Activity放到了一个新的task中,然后用户按下了home键离开了以后,必须要有一种方式能让用户返回到原来的task。有一些entity(比如提醒)总是在外部的task中打开Activity,而不是在他们自己的task中,所以,他们总是会在intent中给startActivity()传递FLAG_ACTIVITY_NEW_TASK。如果你有一个可以被外部的entity使用这个flag来调用的Activity,要注意用户有一种独立的返回到启动它的那个task的方式,比如:按下启动的icon(task的根Activity的intent
filter包含了CATEGORY_LAUNCHER,参考下面的开始一个task章节)。

(2)当Activity把它的allowTaskReparenting设置为true的时候。在这种情况下,Activity可以从启动它的task转移到有相同affinity的task,当task转到前台的时候。

比如说,一个报告选中城市天气状况的Activity被定义成旅游应用的一部分,天气Activity跟同应用中别的Activity有相同的affinity,使用这个属性就允许re-parenting。当某个Activity启动了天气Activity的时候,一开始的时候天气Activity跟启动他的Activity是在同一个task的。但是,当旅游应用的task转到前台的时候,天气Activity会被重新放置到旅游的task中,并在其中进行显示。

注意:从用户的角度来看,如果一个apk包含了多个“应用”的话,你可能就会使用taskAffinity给跟多个“应用”都有关联的Activity赋予不同的taskAffinity。

清空back stack

如果用户长时间离开一个task,系统会清理掉task中的所有的Activity,只保留根Activity。当用户返回到这个task的时候,只有根Activity会被重建。系统之所以这么做是因为当一段时间以后,用户很有可能已经抛弃掉他们之前的动作,返回到这个task是想做一些新东西。

Activity有一些属性可以用来修改这种行为:

alwaysRetainTaskState

如果task的根Activity的这个属性被设置为true的话,上面描述的那种行为就不复存在了。就算是长时间置后台,task仍然会在back stack中保留所有的Activity。

clearTaskOnLaunch

如果task的根Activity的这个属性被设置为true的话,只要用户离开task或者是返回到task的时候,stack都会被清理到只剩下根Activity。换句话说,这跟alwaysRetainTaskState恰好相反。就算是用户只离开了task一小会,当用户返回的时候task将会是它的初始的状态。

finishOnTaskLaunch

这个跟clearTaskOnLaunch很相似,但是它是作用与单个的Activity而不是整个的task。它也会导致Activity销毁,包括根Activity。当这个属性被设置为true的时候,Activity只有在当前回话里属于task的一部分,一旦用户离开,返回的时候Activity将不复存在。

开始一个task

要想把Activity设置为task的起点,只要给它的intent filter里面添加"android.intent.action.MAIN"的action并且"android.intent.category.LAUNCHER"的category就可以了。

比如:

<activity ... >
    <intent-filter ... >
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    ...
</activity>


这种类型的intent filter会让这个Activity以icon和label的形式展示在应用的launcher里面,这让用户可以启动这个Activity,然后可以在Activity启动以后的任何时候,都可以返回到它创建的task。

第二点非常重要,用户必须能够可以离开一个task然后可以使用Activity的launcher再回到它。基于这个原因,"singleTask"和"singleInstance"这两个把Activity标记为总是启动一个新的task的launch mode,只能当Activity的intent filter中包含ACTION_MAIN and a CATEGORY_LAUNCHER的时候才可以使用。假如没有这两个filter会怎样呢?intent启动了一个"singleTask"的Activity,初始化了一个新的task,用户在这个task上工作了一段时间。然后用户按下了home键,这个task会被放置到后台,然后变得不可见了。现在,用户就没有办法能够再回到这个task了,因为在应用的launcher里面找不到这个Activity。

在那些不需要让用户返回到Activity的场景,可以把<activity>的finishOnTaskLaunch属性设置为true。

跟多关于Activity和task是如何在overview screen中进行展现和管理的内容请参考Overview Screen(http://developer.android.com/guide/components/recents.html)。

做了一个小实验:

1.standard

<activity
    android:name="com.example.launchmodedemo.FirstActivity"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<activity android:name="com.example.launchmodedemo.SecondActivity" 
android:launchMode="standard"/>


FirstActivity->SecondActivity->FirstActivity->SecondActivity

FirstActivity<-SecondActivity<-FirstActivity

输出:

11-03 13:29:53.625: E/test(6173): FirstActivity,task id = 140,hashcode=1093231424

11-03 13:29:58.476: E/test(6173): SecondActivity,task id = 140,hashcode=1093341792

11-03 13:30:00.906: E/test(6173): FirstActivity,task id = 140,hashcode=1093412984

11-03 13:30:02.094: E/test(6173): SecondActivity,task id = 140,hashcode=1093481920

(1)同一个task

(2)每次都会创建新实例

(3)返回的时候,依次返回。

FirstActivity->SecondActivity->SecondActivity

FirstActivity<-SecondActivity

输出:

11-03 13:31:30.390: E/test(6275): FirstActivity,task id = 142,hashcode=1093205808

11-03 13:31:32.383: E/test(6275): SecondActivity,task id = 142,hashcode=1093315752

11-03 13:31:33.422: E/test(6275): SecondActivity,task id = 142,hashcode=1093387000

(1)同一个task

(2)从SecondActivity进入SecondActivity,也会创建新实例

(3)返回的时候,是从SecondActivity返回到SecondActivity,再返回到FirstActivity。

2.singleTop

<activity
    android:name="com.example.launchmodedemo.FirstActivity"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
        
<activity android:name="com.example.launchmodedemo.SecondActivity" 
android:launchMode="singleTop"/>


FirstActivity->SecondActivity->FirstActivity->SecondActivity

FirstActivity<-SecondActivity<-FirstActivity<-

输出:

11-03 13:33:41.836: E/test(6803): FirstActivity,task id = 145,hashcode=1093231608

11-03 13:33:45.969: E/test(6803): SecondActivity,task id = 145,hashcode=1093341744

11-03 13:33:47.039: E/test(6803): FirstActivity,task id = 145,hashcode=1093412936

11-03 13:33:48.101: E/test(6803): SecondActivity,task id = 145,hashcode=1093481872

与standard相同。

FirstActivity->SecondActivity->SecondActivity

FirstActivity<-

输出:

11-03 13:34:56.617: E/test(6856): FirstActivity,task id = 147,hashcode=1093198584

11-03 13:35:00.336: E/test(6856): SecondActivity,task id = 147,hashcode=1093308720

11-03 13:35:01.406: E/test(6856): SecondActivity,onNewIntent, task id = 147,hashcode=1093308720

(1)同一个task

(2)从SecondActivity进入SecondActivity,并不会创建新实例,而是调用了onNewIntent。

(3)返回的时候,从SecondActivity直接返回到FirstActivity。

3.singleTask

<activity
    android:name="com.example.launchmodedemo.FirstActivity"
    android:label="@string/app_name"
    android:launchMode="singleTask" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
        
<activity android:name="com.example.launchmodedemo.SecondActivity" 
android:launchMode="standard"/>


MainActivity->FirstActivity->SecondActivity->FirstActivity->SecondActivity

208 ->209(1093202608)->209(1093345824)->209(1093202608)->209(1093447072)

MainActivity<-FirstActivity

输出:

(1)MainActivity打开FirstActivity是不同的task

(2)FirstActivity打开SecondActivity,同一个task。然后再打开FirstActivity,因为已经存在,所以直接调用FirstActivity的onNewIntent,

此时FirstActivity在栈顶,也就是说,已经把SecondActivity移除了。再打开SecondActivity,会重建一个SecondActivity。

(3)返回的时候,是从SecondActivity->FirstActivity->MainActivity。

4.singleInstance

<activity
    android:name="com.example.launchmodedemo.FirstActivity"
    android:label="@string/app_name"
    android:launchMode="singleInstance" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>


<activity android:name="com.example.launchmodedemo.SecondActivity"

android:launchMode="standard"/>

MainActivity->FirstActivity->SecondActivity->FirstActivity->

215 ->216(1093202608)->217(1093345664)->216(1093202608)->217(1093345664)

MainActivity<-FirstActivity

(1)MainActivity打开FirstActivity是不同的task

(2)FirstActivity打开SecondActivity,也是不同的task,因为singleInstance自己位于一个task中。再打开FirstActivity会把FirstActivity置前台。

再打开SecondActivity(这里很奇怪,并没有新创建SecondActivity,而是直接使用的原来的SecondActivity)。

(3)返回的时候,从SecondActivity->FirstActivity->MainActivity。

注意:

(1)MainActivity是在另一个应用中,代码如下:

Button btn1 = (Button) this.findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String packageName1 = "com.example.launchmode";
String className = "com.example.launchmodedemo.FirstActivity";
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName(packageName1, className);
intent.setComponent(cn);
startActivity(intent);
MainActivity.this.startActivity(intent);
}
});


(2)SecondActivity的launchMode是standard,修改FirstActivity的launchMode进行测试。因为这两个参数只能作用于能在launch列表出现的那些Activity。

测试代码在这里:http://download.csdn.net/detail/goldenfish1919/8115145

(3)关于singletask补充一下,如果是在同一个app中,A是standard,B是singletask,C是standard,A启动B,B不会放在单独的task中,而是跟A在同一个task中。如果A->B->C->B,C到B的时候,会调用B的onNewIntent,并且C会被移出栈,此时back会直接到A。如果有另一个app2,app2的main启动了app的A,此时main和A是在同一个task中,此时的A再启动B,B会在另一个task中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: