android 启动模式

本文基于http://developer.android.com/guide/components/tasks-and-back-stack.html 的学习,中文译文http://www.cnblogs.com/popapa/p/android_tasks-and-back-stack.html,大家可以多看看呆呆大侠的博客,学习起来通熟易懂。

android启动模式跟任务和任务栈是有关的,而查看activity栈,这就需要用到adb命令:adb shell dumpsys activity。另外可以通过代码获取task的id,代码如下:

public void logStack(String tag){
        ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> runningTaskInfoList =  am.getRunningTasks(1);
        for (ActivityManager.RunningTaskInfo runningTaskInfo : runningTaskInfoList) {
            Log.e(tag, "id: " + runningTaskInfo.id);
            Log.e(tag,"description: " + runningTaskInfo.description);
            Log.e(tag,"number of activities: " + runningTaskInfo.numActivities);
            Log.e(tag,"topActivity: " + runningTaskInfo.topActivity);
            Log.e(tag,"baseActivity: " + runningTaskInfo.baseActivity.toString());
        }
    }
使用adb shell dumpsys activity:


这里代表android.intent.action.MAIN的是MyActivity,在其上有TwoActivity、ThreeActivity,ThreeActivity在栈顶。

启动模式详解:

"standard" (默认模式)
默认值。系统在启动 Activity 的任务中创建一个新的 Activity 实例,并把 Intent 传递路径指向它。 该 Activity 可以被实例化多次,各个实例可以属于不同的任务,同一个任务中也可以存在多个实例。
"singleTop"
如果 Activity 已经存在一个实例并位于当前任务的栈顶,则系统会调用已有实例的  onNewIntent() 方法把 Intent 传递给已有实例,而不是创建一个新的 Activity 实例。 Activity 可以被实例化多次,各个实例可以属于不同的任务,同一个任务中可以存在多个实例(但仅当回退栈顶的 Activity 实例不是该 Activity 的)。

比如,假定某个任务的回退栈中包含了根 Activity A 和 Activity B、C、D(顺序是 A-B-C-D;D 在栈顶)。 这时,传来了一个启动 Activity D 的 Intent。 如果 Activity D 的启动模式是默认的"standard",则会启动 Activity D 类的一个新实例,栈的内容变为 A-B-C-D-D。 但是,如果 Activity D 的启动模式是"singleTop",则已有的 Activity D 实例会通过 onNewIntent() 接收这个 Intent,因为该实例位于栈顶——栈中内容仍然维持 A-B-C-D 不变。 当然,如果此 Intent 是要启动 Activity B 的,则 Activity B 的一个新实例还是会被加入栈中,即使 Activity B 的启动模式是"singleTop"也是如此。

注意: 一个 Activity 的新实例创建完毕后,用户可以按 回退键返回前一个 Activity。 但是如果是由 Activity 的已有实例来处理刚到达的 Intent ,那用户就无法用 回退键回到  onNewIntent() 中 Intent 到来之前的 Activity 状态了。
"singleTask"
系统将创建一个新的任务,并把 Activity 实例作为根成员放入其中。 但是,如果该 Activity 已经在其他任务中存在实例了,则系统会调用已有实例的 onNewIntent() 方法把 Intent 传给已有实例,而不是再创建一个新实例。 本类 Activity 同一时刻只能存在一个实例。
注意: 虽然 Activity 启动了一个新的任务,但用户仍然可以用 回退键返回前一个 Activity。
"singleInstance"
除了系统不会把其他 Activity 放入当前实例所在的任务之外,其他均与 "singleTask"相同。 Activity 总是它所在任务的唯一成员;它所启动的任何 Activity 都会放入其他任务中。

再举个例子,Android 的浏览器应用就把 web 浏览器 Activity 声明为总是在它自己独立的任务中打开——把 <activity> 设为singleTask模式。 这意味着,如果某个应用提交 Intent 来打开 Android 的浏览器,则其 Activity 不会被放入该应用所在的任务中。 而是或为浏览器启动一个新的任务;或者浏览器已经在后台运行,只要把任务调入前台处理新的 Intent 即可。

无论 Activity 是在一个新的任务中启动,还是位于其他已有的任务中,用户总是可以用回退键返回到前一个 Activity 中。 但是,如果启动了一个启动模式设为singleTask的 Activity,且有一个后台任务中已存在其实例的话,则这个后台任务就会整体切换到前台。 这时,当前的回退栈中就包含了这个转入前台的任务中的全部 Activity,且位置是在栈顶。 图 4 就展示了这种场景。


图 4. 启动模式为“singleTask”的 Activity 如何加入回退栈的示意。 如果 Activity 已经是在后台任务中并带有自己的回退栈,则整个后台回退栈都会被带到前台,并放入当前任务的栈顶。

注意: 利用 launchMode 属性为 Activity 设置的启动模式可以被启动 Activity 的 Intent 标志位属性所覆盖,这将在下一节中描述。


这里我是直接复制呆呆大虾博文中启动模式翻译的部分,详细请翻阅呆呆大虾的博客。

对于standard模式和singleTop模式,看字面意思就明白了,这里主要详解singleTask和singleInstance。

思路就是创建两个apk,操作activity的访问。这里新建了一个launchmode和launch2这两个工程。具体activity访问过程为:



而launch2工程中就两个activity,MyActivity和Two2Activity。

先说singleTask:

在launchmode的AndroidManifest中声明OneActivity的启动模式为singleTask,并为其添加过滤:
<intent-filter>
                <action android:name="com.example.launchmode.kedou"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
使launch2中的Two2Activity可以跳转到OneActivity。

第一种情况,app内部跳转:

launchmode工程试验。

从这里发现OneActivity以上的Activity都被弹出销毁了。从FourActivity跳到OneActivity,OneActivity中的onNewIntent()被调用。通过设置根Activity启动模式为singleTask,要退出应用时,通过其他Activity跳转到根Activity,然后再onNewIntent()中finish(),这也是退出应用的方式。

第二种情况:其他app中的Activity访问

从MyActivity依次调到TwoActivity。

点击home键,打开launch2,点击跳到OneActivity。操作之后OneActivity的onNewIntent()被调用了。adb命令查看栈结构,得到


对比上一张图,可得出结论:OneActivity以上的Activity都被弹出销毁了,这和app内部跳转是一样的。点击回退时,先退完launchmode的activity,然后再退launch2中的activity,也就是说如果启动了一个启动模式设为singleTask的 Activity,且有一个后台任务中已存在其实例的话,则这个后台任务就会整体切换到前台。如果按home键后再打开对应的app,回退只会退掉该app栈。

反过来操作,先操作launch2,launch2启动launchmode的OneActivity。这里大家动手试试吧,说了感觉啰嗦,还不如直接动手调试理解的快。源码在最后面。

对于singleInstance:

将OneActivity的启动模式改为singleInstance,然后进行跳转操作。发现OneActivity的task在app都退出后还存在。通过清理可删除。大家动手试试就知道了。

源码:http://yunpan.cn/cFHEMPTyCRbNG (提取码:d027)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值