SingleTop与SingleTask在实际应用中的微妙之处
在Android的launchMode
中有四个可选模式,分别是singleTop
,singleTask
,standard
,singleInstance
,它们分别代表一个activity的几种打开方式,或者叫存在方式。
拿浏览器的操作来对比的话,从后往前讲,singleInstance
就是在新窗口中打开,打开后就会有两个窗口并列显示,Android中会新开辟一个activity堆栈,使用这种方式会造成一个现象,当你按目录键,将手机中已打开的app列出来时,会发现一个app有两个选项卡,让人觉得是两个app一样,该种方式实际中并不常见,目前仅发现小程序采用了该种方式;standard
就相当于点一个链接打开一个新的标签页,Android中表示每次都新建一个Activity实例。这两个是可以进行对比的,没什么问题,但是两外两个对比起来就略微有些问题,singleTask
和singleTop
都可以当作是在当前页面打开的意思,就是你点击一个链接并非打开一个新窗口或者打开一个新的标签页,而是直接在当前页面跳转,其中Github就是典型案例,但是Android中又略微不同,不同之处主要在于重复打开同一页面所带来的影响,与浏览器截然不同。
singleTask
和singleTop
这两种方式在实际应用中有着诸多的微妙之处:
设置了SingleTask
这种存在方式,Android中它维持一个Activity堆栈(注意是Activity堆栈,不是java中说的堆栈,以下为方便简称堆栈,注意区别)中的Activity都是独一无二的,就是说同一个Activity实例不会重复创建。
设置了SingleTop
这种存在方式,在一个堆栈中,同一个Activity不一定是独一无二的,只有当该Activity存在于栈顶的时候才不会新建,如果不在栈顶,Android同样会重新创建该Activity实例。
Android中的activity采用层级式显示,新打开的页面一般都是铺盖在上层,返回的时候好似一层层的剥离,但是实际业务总是千奇百怪,纷繁复杂,总有些逻辑不能按照既定的规则来走,singleTask
就是这种怪胎,当你打开一个Activity,如果该Activity设置了这种launchMode
,那么该Activity没有创建一切都好,但是如果已经创建,该Activity比较霸道,会将堆栈来个釜底抽薪,凡是覆盖在其上层的Activity都会被销毁。singleTop
和singleTask
都不能打开自己,我们在做防快速点击时,如果是为了防止多次startActivity
,可以将目标Act设置为singleTop
,实际业务中,如果不是特别逻辑需求,也应该将所有activity的launchMode
设置为singleTop
。
由于singleTask
的独特性,使它成为了四种launchMode
中最考验逻辑的地方,实际业务中,需要保持唯一性,又需要釜底抽薪作用的,一般都是主页和登陆页。
另外,如果登陆页是app启动后的第一页,如下一样
<activity
android:name=".ui.activity.LoginWebActivity"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden|adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
launchMode
一般为交互体验来说,不应设置为singleTask
,配置了LAUNCHER
策略的activity,无论从何处启动该app都会重新从该activity开始显示,例如上述activity配置了singleTask
,如果该应用使用过程中来了电话,或者退到后台,当再次调用到前台时,LoginWebActivity
将会首先显示。当然,这也算是singleTask
的另一个特点,该特点可以被应用于安全级别较高的app中,例如银行的app,部分银行的app在退到后台再重新打开时,会重新调到登陆页面,有可能利用了该原理。
现在一般的应用都会做token验证,一些重要的接口必须有正确的token才能访问,而token过期则必须回到登陆页面去重新登陆,实际当中我们有些页面进入时可能会同时访问n个接口,如果token此时恰好过期,没有配置launchMode
的登陆页面,可能会陷入一次灾难。