谈一谈 Activity lauchMode 以及 任务栈和返回栈

       

谈一谈 Activity lauchMode 以及 任务栈和返回栈

        Activity 的意思是活动,我们通常称Activity 为 我们用手机看到的页面。

        一个页面可以开启另一个页面。比如 页面A->开启页面B->开启页面A 这时候就有两个页面A了,那么到底应该有一个页面A的实例呢,还是两个呢,我认为,Android 为了解决这样问题,有了启动模式的概念。Android的启动模式有四种 (standard,singleTop,singleTask,singleInstance)。


        页面A->开启页面B->开启页面C 当按返回回到页面B,再按返回回到页面A ,再按返回回到桌面。 我们通常看到的是这样的现象,这是方面用户的习惯,Android 有了这样的设计,那么怎么去实现呢,就有了任务栈的概念 (我对任务栈的理解是,任务栈是 一组关系密切的 Activity 的集合)。


        一:启动模式。

        standard 标准启动模式,比如 页面A->页面B(标准)->页面C->页面B(标准),这时候任务栈的结构是,ABCB ,可以看到这个栈中有两个B的实例,这个是标准启动。

       singleTop 栈顶复用模式,比如 页面A->页面B(singleTop)->页面B(singleTop),这时候任务栈的情况是 AB ,singleTop会栈顶复用,因为任务栈中已经有 B页面了,而且B页面是singleTop模式,所以再启动B页面时候,不会再创建B页面的实例,而是直接用栈顶的B页面的实例,回调B页面的 onNewIntent方法。思考下, 如果 页面A->页面B(singleTop)->页面C->页面B(singleTop)模式,这时候任务栈栈的情况,ABCB,因为B没有在栈顶,所以不会复用。  

       singleTask 刚才说的,页面A->页面B(singleTop)->页面C->页面B(singleTop)这时候,任务栈的情况是 ABCB,我们不希望栈中有两个B页面的实例,怎么办,之后就有了 singleTask模式。 页面A->页面B(singleTask)->页面C->页面B(singleTask),此时任务栈就变成了 AB 因为singleTask会将 页面B的实例之上的页面的实例全部销毁。举个实际中常用到的例子吧,比如说,首页->二级页面->三级页面->首页,我们希望复用首页的实例,销毁中间的页面,这时候,用singleTask就很方便了。

        singleInstance 这个模式比较特殊,singleInstance实例要求自己在一个任务栈中,这个任务栈中不会有其他的Activity实例。

        

        上面介绍的四种模式,介绍的都是一些概念而且都是在一个任务栈中的使用。下面我们说下有多个应用和多个任务栈的情况。也会详细的介绍下对任务栈的理解。

         应用TaskA  页面A->页面B->页面C ->启动应用 TaskB的页面CC(standard模式),查看任务栈的结果(注意CCActivity的taskId和TaskA的页面的 taskId一样,因为这是标准的启动模式)

          


           应用TaskA  页面A->页面B->页面C ->启动应用 TaskB的页面CC(singleTask模式),查看任务栈的结果(注意CCActivity的taskId和TaskA的页面的 taskId不一样)

           

        二. taskAffinity和singleTask的关系

         这时候引出 taskAffinity的概念 (下面深入讲一下 taskAffinity和singleTask的关系)。

         singleTask是和taskAffinity相关的,自己做了实现 standard模式启动一个Activity(指定和包名不同的taskAffinity),实际上这个Activity对应的taskId和启动它的Activity对应的taskId是一样的。如果是singleTask模式启动的话,这个Activity对应的taskId和启动它的Activity对应的taskId是不一样的。所以我们现在认为taskAffinity是和singleTask相关的。


        下面举个例子,TaskB应用启动 AAActivity->BBActivity->CCActivity.注意CCActivity的启动模式是 singleTask。看下图的结果。taskId都是94. 而上一次的实验 同样是 singleTask启动CCActivity,为什么taskId是不同的呢???因为上一次的实验室 taskA 启动的TaskB的CCActivity,taskA对应的taskAffinity默认是自己的包名"com.example.cheng.testtaska",taskB对应的taskAffinity默认是自己的包名"com.example.cheng.testtaskb"。接着说,上一次实验,应用TaskA  页面A->页面B->页面C ->启动应用 TaskB的页面CC(singleTask模式) 这时候,发现CCActivity是singleTask模式启动,这时候检查 TaskA的C页面的taskAffnity和TaskB的CCActivity的taskAffinity是不一样的,所以就开启了一个新的 task。而这次实验,发现BBActivity的taskAffinity和CCActivity的taskAffinity是一样的(都是自己的包名),所以就没有启动新的task。



       三,谈谈对任务栈的理解。

       standard和singleTop情况,都不会开启一个新的任务栈,这种情况,我们先不考虑(因为一个Activity开启Activity无论是自己的应用的Activity还是别的程序的应用的Activity(都是standard或者singleTop模式),这时候只会有一个任务栈,这种情况下,先不做分析)。

      singleInstance 开启的Activity,自己在一个任务栈中,而且这个栈中,只有它自己。所以这种情况,我们也先不分析。

       谈一下singleTask和任务栈。

      第一步实验,桌面Activity启动应用 TaskB AAActivity->BBActivity->CCActivity。按Home键切换到桌面。

                                              启动应用 TaskA AActivity->BActivitiy->CActivity。这时候,我们看下日志。                        

                   

        分析一下日志,我的猜想是桌面应用启动TaskB的AAActivity和TaskA的AActivity,实际上是以 FLAG_ACTIVITY_NEW_TASK 启动了 AAActivity和AActivity(猜想的,因为他们分别对应着两个 taskId)。

       第二步实验,桌面应用 启动 应用 TaskB AAActivity->BBActivity->CCActivity。按Home键切换到桌面。

                                            启动应用 TaskA AActivity->BActivitiy->CActivity ->启动taskB的CCActivity(singleTask模式),我们看下日志。    

               

         我们分析一下日志:   

         TaskB AAActivity->BBActivity->CCActivity按Home键切换到桌面。(此时taskB 任务变成后台任务)

        桌面Activity启动应用 TaskA 的AActivity->BActivitiy->CActivity (前台任务),这时候再启动TaskB的CCActivity ,将后台任务切换到了前台。因为是 singleTask启动模式,所以CCActivity不会重建,而是调用onNewIntent.所以看到的日志是 onResume==CCActivity。这里再详细的补充一下,为什么没有新建task,新创建CCActivity,因为SingleTask模式启动一个Activity,首先先会看返回栈中,是否有这个Acitivity,如果有的话,不会创建,直接用,如果没有的话,会创建新的任务栈,创建此Activity。singleTask模式启动的Activity,在返回栈中,只会有一个。singleInstance创建的Activity在返回栈中只会有一个,而且此Activity自己在一个任务栈。

         再分析一下返回为什么是这个结果。

        TaskA CActivity (前台任务)->TaskB的CCActivity 这时候,将 TaskB的AAActivity->BBActivity->CCActivity 变成了前台任务。所以返回的结果是这样的啦。

     四,对返回栈的理解。

          感 谢月亮与六便士对返回栈详细的讲解,6月25日凌晨,和他讨论到凌晨4点多,有个志同道合的朋友,真的是一件很荣幸的事情。害羞害羞害羞
        
         谈一谈我对返回栈的认识,返回栈是什么呢? AMS 启动Activity,会将这些Activity 放到一个 集合里面,这个集合就是返回栈。每一个Activity 都包含着taskId等信息。相同的taskId的Activity们,他们在一个任务栈中。

        当一个Activity启动一个Activity的时候(我们其实没有必要区分是不是一个应用,因为Android在这块对是不是同一个应用的概念比较弱化的,他们就是Activity),如果是standard模式和singleTop模式的时候,会将启动的Activity的taskId赋值成自己的taskId。

       当一个Activity启动一个Activity(singleTask模式)的时候,先从返回栈中,查看有没有这个Activity(taskAffinity 是manifest指定的或未指定用默认的),如果有的话,直接用,并将和这个activity taskId 一样的activity调到前台任务中。如没有话,创建新的Activity和新的任务栈。

     分析返回栈,给人的感觉是,一个一维的集合,我们用的时候,再从这个一维的集合里面去组织成自己想要的结果。


    最后,简单的谈一下 Intent Flag和launchMode的区别吧。月亮和六便士总能抓到问题的本质,FLAG是开启方控制被开启方,启动模式是自己控制自己。FLAG会覆盖启动模式。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值