Android原理探究:Activity任务栈Task的简单探讨

来源:互联网 发布:地下城组队网络冲突 编辑:程序博客网 时间:2024/05/16 15:07

转载请注明出处,谢谢~

http://blog.csdn.net/net_168/article/details/50958700


案例

某天上班,小明正在调试前些日子开发的支付宝应用内支付功能。当他兴冲冲打开支付页面,不小心把APP切到后台,等返回APP时却发现支付界面莫名其妙消失了,又发现那个支付界面又偷偷跑到了隔壁支付宝APP那边。小明突然感觉背脊一凉,产品经理那阴冷冷的话仿佛音绕耳旁:搞定这个BUG,你只有两个小时。可是左猜又蒙想不起个所以然,这不对呀,小明的世界观开始出现裂隙;不行,得去请教老司机,错了,是求助老员工。而老司机听了小明的疑惑后色眯眯的说,这是正常的现象呀!纳尼~小明的世界观彻底的崩溃了,还能这么玩。

AndroidtaskAffinityTask

在老司机的引路下,小明翻阅了几篇82年的文档压压惊。发现,貌似跟activity里面的属性taskAffinity这个东西有点关系。这里需要科普下:taskAffinity中文翻阅“亲和力”,说人话就是“Activity抱团打BOSS”;然而文档又说明拥有相同taskAffinityActivity一般情况下会组成一个Task集合。

而这个Task干嘛的?举个栗子:当我们从桌面启动了应用A,应用A里面包含了Activity1Activity2,估计记做A1A2;如果这时又有一个应用B,拥有B1B2B3这些Activity。那么我们可以姑且认为他们不是一伙的:A1A2属于一个Task,而B1B2B3属于另外一个Task。然而谷歌设计这个Task到底有什么不可告人的秘密呢?

带着然并卵的疑问,小明又发现了谷歌对于Task用途的一个权威解释:Task的引入是为了确保Activity的启动和退出的顺序,顺便来个情景分析,如果系统中Activity的顺序是A1-A2-A3-B1-B2-C1-C2,那么我们要在C应用中C2这个Activity启动属于B应用的B1这个Activity,那么问题来了:

1、程序要启动B1,但从用户角度来看,可能是要启动B2,因为B1B2是两个相关联的Activity,且B2B1之后。那么虽然是启动B1,既然B2已经在运行了,那就启动B2吧。

2、如果已经从C2跳转到B2,那么在B2进行”BACK”键回退时,是应该回到C2呢还是B1呢?

为了解决这两个问题,谷歌引入了Task当启动Activity时,系统会根据ActivitytaskAffinity属性去找对应的Task(前提是采用了IntentFlagNEW_TASK配置)。如果存在相对应的TASKB1-B2);这不是找到组织了嘛,那就强行抱团插队到TASK的最前面,也就是A1-A2-A3-C1-C2-B1-B2,那么B2回退时,顺理成章得回到B1,也就解决了上面那两个问题。

ActivitylaunchModeFlag

那么什么会影响Activity的不同Task归属呢?智商捉鸡的小明隐隐约约想起了一直熟背的Activity四大启动模式和一直觉得很神秘的Flag,很明显他们都是对于分配Activity从属哪个Task的决定性因素。小明翻阅他的开发红宝书,记有如下内容:launchModestandardsingleTopsingleTasksingleInstance等四种模式;FlagFLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_NO_HISTORY等等等(PS:那么多,记得下也记不住)。可是他们两种有什么区别么?鬼知道呀。能用就用呗~

可是,launchModeflag是怎么决定Task的归属和顺序的?带着这些疑惑,小明是茶也不思、饭也不香。于是,又从各个小道打探消息,终于找茫茫百度之间找到这么一句话:Android关于Task的设计理念有一个简单的原则,如果是跨Task切换,调用者是没有权利去更改被调Task里面的Activity的顺序,除非被调用者自己声明了某些属性。

稍微翻译一下,也就是说如果Activity顺序是A1-A2-B1-B2-B3-C1-C2-C3那么在C3中启动B的三个Activity里面任意一个,其结果只能是 A1-A2-C1-C2-C3-B1-B2-B3,只能是整个B栈的切换调整;而如果C3启动C中任意的Activity的话,是可以对C中的Activity的顺序进行重排的,因为C正在与用户交互,系统认为当前交互的任务(Task)中切换Activity是合法的。在这个设计原则前提下,我们就很容易对各种启动方法导致的启动结果做出一个分析:

进行Task切换的方法有两种,一种是在AndroidManifest.xml里面声明Activity自身的启动属性,另外一种则是启动时为Intent添加对应的Flag。东西比较多,小明比较懒就没一一罗列出来。各种模式各种标识,看起来炒鸡复杂~

但是,小明又发现有前辈总结了这么一个大定律。记录如下:虽然Activity的启动方式繁杂,但总得来说分为三种主要类型:第一类是为了完成在Task之间的切换;第二类是为了完成在当前Task改变其中的Activity的顺序;最后一类则是Task在切换时内部自动重排Activity的顺序。

稍微举个例子来加深印象:

第一类:在Task之间的切换,我们可以通过在intent里面设置FLAG_ACTIVITY_NEW_TASK来启动Activity,很显然,如果intent所匹配到的Activity已经存在于某个Task里面,那么就直接切换到这个Task;如果没有则会创建一个新的Task来容纳该Activity。或者是调用者自身就希望出现在一个新的Task里面,例如launchModesingleInstance属性。

第二类:在同一个Task里面调整Activity的顺序,但需要注意的是只能调整当前Task里面的Activity的顺序,例如我们可以使用CLEAR_TOP这个flag来清楚目标Activity上面的其他Activity,或者使用NO_HISTORY使得目标Activity常驻在Task之中,或者使用launchModesingleTask来显示类似的效果。

第三类:让被调Task再启动前主动重排,这个并不多用,简单说是例如发起intent的标识为RESET_IF_NEEDED或者在清单文件里面使用android:clearTaskOnLauch等属性,字面意思很清楚了,这里就不往深讲了。

回顾

经过小明风风雨雨的研究心路历程,小明对开头的问题作了如下分析:

1、在APP中启动了支付页面,但是支付页面是从属于另外的一个APP(也就是支付宝);所以该支付页面一般来说也就是属于另外一个Task,暂且把自己的APP所属的Task记为A、支付宝所属的Task记为B

1、有人告诉小明桌面其实也是一个APP,桌面页面所在的Activity当然也是从属于某一个Task里面,记桌面所在的TaskC

2、此时我们可以知道Activity的顺序为B1-A1-A2-A3-C1,那么我们从APP切回桌面时,顺序应该变成A1-A2-A3-C1-B1。那么我们如果继续点击我们APP的图标,很明显顺序应该是C1-B1-A1-A2-A3,也就是C1这个支付页面就消失了;如果不点击APP图标而点击支付宝图标,顺序则是A1-A2-A3-B1-C1,很明显现在调起来的是支付界面。

完结~小明突然觉得自己挺叼炸天的O(_)O哈哈~



4 0
原创粉丝点击