美文网首页组件android技术杂荟Android架构设计
深入理解android 启动模式--singleTask

深入理解android 启动模式--singleTask

作者: 岁月留痕 | 来源:发表于2017-04-25 16:58 被阅读11117次

Android启动模式分为Standard,SingleInstance,SingleTop,SingleTask,四种模式,基本上每次面试都是必面。
今天打算自己从Activity 生命周期变化,和onNewIntent ,taskAffinity,是否可以替代singleTask这些角度来重新理解下

SingleTask

依次启动A---B----C三个界面 ,然后从C 跳回B,其中B界面设置为SingleTask
Log 日志如下:

04-25 11:15:41.880 4197-4197/wdwd.com.androidpractice E/AActivity: onCreate
04-25 11:15:41.881 4197-4197/wdwd.com.androidpractice E/AActivity: onResume

04-25 11:16:14.394 4197-4197/wdwd.com.androidpractice E/BActivity: onCreate
04-25 11:16:14.395 4197-4197/wdwd.com.androidpractice E/BActivity: onResume

04-25 11:16:34.578 4197-4197/wdwd.com.androidpractice E/CActivity: onCreate
04-25 11:16:34.578 4197-4197/wdwd.com.androidpractice E/CActivity: onResume

04-25 11:16:55.497 4197-4197/wdwd.com.androidpractice E/BActivity: onNewIntent
04-25 11:16:55.497 4197-4197/wdwd.com.androidpractice E/BActivity: onResume
04-25 11:16:55.805 4197-4197/wdwd.com.androidpractice E/CActivity: onDestroy

可以发现B在第一次启动时正常,当从C重新启动时,这个时候B已经存在,C会被Destroy,然后依次调用B页面的onNewIntent(),onStart(),onResume,这时,B的onCreate方法没有调用,我们可以判断B没有重新生成,而B之上的C被干掉了
这个onNewIntent是干嘛的呢,测试从C跳转到B时传递参数会怎样呢,修改了下代码,A---B 传入参数 2, C----B 时传入参数1

04-25 11:32:40.823 5567-5567/wdwd.com.androidpractice E/BActivity: onCreate
04-25 11:32:40.824 5567-5567/wdwd.com.androidpractice E/BActivity: onResume2

04-25 11:33:08.186 5567-5567/wdwd.com.androidpractice E/BActivity: onNewIntent1
04-25 11:33:08.186 5567-5567/wdwd.com.androidpractice E/BActivity: onResume2

04-25 11:33:08.488 5567-5567/wdwd.com.androidpractice E/CActivity: onDestroy

可以发现 onNewIntent 是在界面没有重新创建时调用的,从A跳过来的Intent依然保存着,onNewIntent 从字面意思来理解重新创建了一个Intent 来接收新的意图,可以在onNewIntent方法中重新设置Intent

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        Log.e("BActivity","onNewIntent"+intent.getStringExtra("cyy"));
    }

使用场景分析

singleTask 不能用代码生成,暂时发现只能在清单文件中定义,有人说和FLAG_ACTIVITY_NEW_TASK 有相似之处,还没有尝试,使用了singleTask 后,主要的特点会将该activity 之上的activity 清空,可以用来消除交互界面的嵌套循环

taskAffinity

为什么taskAffinity与singleTask一起介绍,因为与其他模式一起使用时taskAffinity改变,并不会改变taskid,而singleInstance即使不改变taskAffinity 也会改变takid
另外taskAffinity 可以与 android:allowTaskReparenting="true"一起用

allowTaskReparenting用来标记Activity能否从启动的Task移动到taskAffinity指定的Task,默认是继承至application中的allowTaskReparenting=false,如果为true,则表示可以更换;false表示不可以

taskAffinity默认是包名,现在将BActivity 设置为其他taskAffinity

  <activity android:name=".lancumode.BActivity"
            android:launchMode="singleTask"
            android:taskAffinity="wdwd.cyy">

继续依次从A---B---C 启动会发生什么呢

04-25 14:35:48.994 20912-20912/wdwd.com.androidpractice E/AActivity: onCreate
04-25 14:35:48.994 20912-20912/wdwd.com.androidpractice E/AActivity: onResume2283+++true

04-25 14:36:32.937 20912-20912/wdwd.com.androidpractice E/BActivity: onCreate
04-25 14:36:32.938 20912-20912/wdwd.com.androidpractice E/BActivity: onResume2
04-25 14:36:32.938 20912-20912/wdwd.com.androidpractice E/BActivity: onResume2284+++true

04-25 14:37:13.159 20912-20912/wdwd.com.androidpractice E/CActivity: onCreate
04-25 14:37:13.159 20912-20912/wdwd.com.androidpractice E/CActivity: onCreate2284+++false
04-25 14:37:13.160 20912-20912/wdwd.com.androidpractice E/CActivity: onResume

从C----B
04-25 14:37:34.481 20912-20912/wdwd.com.androidpractice E/BActivity: onNewIntent1
04-25 14:37:34.481 20912-20912/wdwd.com.androidpractice E/BActivity: onResume2
04-25 14:37:34.481 20912-20912/wdwd.com.androidpractice E/BActivity: onResume2284+++true

04-25 14:37:34.787 20912-20912/wdwd.com.androidpractice E/CActivity: onDestroy

好像和前面没什么变化,2283 2284是当前页面所属的task,true和false是是否该task的根节点,我们发现C并没有更改taskAffinity 但是它的taskid 还是发生了改变

这时按下HOME键,再点击应用图标,我们发现这时启动的居然是AActivity

一定要使用singleTask吗

我们发现singleTask 是写死在xml当中,是否太重,那么有什么可以替代的呢?
目前发现如果不修改taskAffinity 也就是第二节的效果,完全可以FLAG_ACTIVITY_CLEAR_TOP + Intent.FLAG_ACTIVITY_SINGLE_TOP来代替singleTask 。
另外还有一个标识Intent.FLAG_ACTIVITY_REORDER_TO_FRONT不会销毁该Activity 之上的activity,只将要启动的Activity 放到栈顶,

Intent.FLAG_ACTIVITY_SINGLE_TOP的意思是如果该activity在栈顶则不会重新创建,只会调用onNewIntent---onStart()---onResume

相关文章

网友评论

  • 373368212db0:楼主麻烦看下我这个场景:
    启动页AActivity设置为singleTask,跳转到BActivity(为普通模式),这个时候推到home页面,再点击icon打开app,先执行了AActivity的onNewIntent,这是为什么呢?AActivity和BActivity都没有设置taskAffinity参数。
  • 男子汉大豆腐:singleTask 模式应该是和 FLAG_ACTIVITY_CLEAR_TOP 表现一样,和
    FLAG_ACTIVITY_NEW_TASK 除了名字,没有什么共同之处,另外,FLAG_ACTIVITY_NEW_TASK 可以配合其他 FLAG,有更复杂的行为,表现要复杂得多。
  • one_cup:楼主你觉得点击Home键之后吗,再重新点击图标启动的是AActivity是为什么?
    one_cup:@岁月留痕 楼主说的对,应该是启动默认包名的task,这个task中只有AActivity,同时猜测,系统当时并不知道另一个task的名字是什么。https://blog.piasy.com/2017/01/16/Android-Basics-Task-and-LaunchMode/
    岁月留痕:这个可能要看下罗升阳的Android应用程序启动过程源代码分析吧
    我理解的是应用主task栈中只有aactivity,点击图标的时候会先启动当前栈顶部的activity,而这时bc已经在另外一个栈中

本文标题:深入理解android 启动模式--singleTask

本文链接:https://www.haomeiwen.com/subject/ixfvzttx.html