在公司内部每周分享会上听到的总结,用自己的话再写一遍,算是加深记忆了。
Activity是Android的四大组件之一,Activity的启动模式也是必须要掌握的基础知识之一。
Activity的启动模式有4种:standard,singleTop,singleTask,singleInstance,默认方式是standard。
Task,实际上是一个栈管理。Android中把一组Activity之间的跳转和回退的动作,当做一个“任务”来理解。当我们启动一个新activity时,执行的是入栈操作,会把activity压入栈。当点击返回时,执行的是出栈操作,让当前activity出栈,这样就显示出了上一个activity。
taskAffinity,Activity的一个属性,可以在Manifest中设置。它是Activity所在Task的Task名字。默认是包名。
一、设置模式可以通过在manifest里配置也可以通过Intent的flag来设置,注意点有如下几个;
1.singleInstance只能在Manifest里配置;
2.Manifest中的SinglelInstance和SinglelTask模式配置优先级要高于Intent里的flag,什么意思?就是如果两者出现冲突的话,会以Manifest里的为准,Intent里的相关flag会无效。详见源码。
3.singleTop的Intent flag配置是:Intent.FLAG_ACTIVITY_SINGLE_TOP;
4.singleTask的Intent flag配置是:Intent.FLAG_ACTIVITY_NEW_TASK;
二、验证方法:
通过命令:adb shell dumpsys activity activities查看,会看到类似这样的信息:
TaskRecord{74f2854 #25155 A=me.majiajie.pagerbottomtabstriptest U=0 sz=1}
Run #4: ActivityRecord{56baba7 u0 me.majiajie.pagerbottomtabstriptest/.MainActivity t25155}
如果遇到如下错误:
error: unknown host service
通过命令:netstat -ano|findstr "5037"找到占用该端口的进程后,根据进程ID到任务管理器里关闭该进程;然后再重新尝试adb命令。
三、各模式含义总结:
3.1 standard
每次startActivity都创建新的实例;
3.2 singleTop
在启动一个singleTop模式的Activity时,如果当前Task的栈顶恰好就是该Activity,则不会重新创建,会通过onNewIntent方法通知Activity。否则,与standard模式一样,创建新的实例;
3.3 singleTask
如果当前Task里已经有该Activity时,则会把位于该Activity之上的Activity都弹出栈,保持该Activity位于栈顶;如果B是singleTask模式,Task-1里有A、B、C三个Activity,A->B->C->B启动的结果是Task-1里只有A-B;C被出栈这一点会比较出乎意料。
3.4 singleInstance
就是一个单例模式,每个Activity一个Task,不管Task名字是否相同;每个Task里只有一个这样的Activity实例。
四、混合模式
4.1 当singleInstance遇到singleTask时,结果会是啥?
示例中,MainActivity是默认的standard、Main2Activity是singletask模式;Main3Activity是singleInstance模式,Main4Activity是singleTask模式;
启动顺序是:MainActivity->Main2Activity->Main3Activity->Main4Activity。
由下面的结果得出两个结论:
1.从MainActivity->Main2Activity可以看出,singleTask的含义并不是说一定要新创建一个Task,只是要保证当前Task里只有一个这个Activity的实例;
1. 从Main2Activity->Main3Activity、从Main3Activity->Main4Activity可以看出,singleInstance模式的Activity是独占一个Task的。
3.同样是singleTask,为什么Main2Activity、Main4Activity的待遇不同?原因应该是Main3Activity的特殊性所致,Main4Activity是迫不得已才另起一个Task的。
Running activities (most recent first): TaskRecord{fa02b1d #25180 A=chwn.wuba.com.activitymode U=0 sz=3} Run #4: ActivityRecord{cb21ffc u0 chwn.wuba.com.activitymode/.Main4Activity t25180} TaskRecord{2b155a0 #25181 A=chwn.wuba.com.activitymode U=0 sz=1} Run #3: ActivityRecord{6a84ea3 u0 chwn.wuba.com.activitymode/.Main3Activity t25181} TaskRecord{fa02b1d #25180 A=chwn.wuba.com.activitymode U=0 sz=3} Run #2: ActivityRecord{8437a4 u0 chwn.wuba.com.activitymode/.Main2Activity t25180} Run #1: ActivityRecord{c3147f4 u0 chwn.wuba.com.activitymode/.MainActivity t25180}
4.2 接着上面的例子,让Main4Activity启动Main2Activity。
启动顺序是:MainActivity->Main2Activity->Main3Activity->Main4Activity->Main2Activity。
猜猜什么结果?
答案揭晓:
Running activities (most recent first): TaskRecord{44845e0 #25191 A=chwn.wuba.com.activitymode U=0 sz=2} Run #3: ActivityRecord{6ca0d17 u0 chwn.wuba.com.activitymode/.Main2Activity t25191} TaskRecord{6749e59 #25192 A=chwn.wuba.com.activitymode U=0 sz=1} Run #2: ActivityRecord{226d2a0 u0 chwn.wuba.com.activitymode/.Main3Activity t25192} TaskRecord{44845e0 #25191 A=chwn.wuba.com.activitymode U=0 sz=2} Run #1: ActivityRecord{3ffd7e3 u0 chwn.wuba.com.activitymode/.MainActivity t25191}
着实有点难以理解。Fuck the source code吧,只能。
视觉上的表现还是符合我们的理解的:
当Main4Activity->Main2Activity时,系统默认的跳转动画是返回动画,即Main4Activity是被出栈回落到了Main2Activity;这一点与Main4Activity与Main2Activity处于同一个栈的情况一致;
然后在Main2Activity界面按返回键,先回到MainActivity,最后回到Main3Activity。
五、感悟
要想搞明白某个知识点,必须得亲手实验,断不可臆测。