引言
Android LaunchMode是一个重要概念,它定义了Activity的启动模式,决定了Activity在不同情况下如何启动。
可通过在AndroidManifest.xml文件中配置,可以影响Activity的实例化和调用栈管理。
LaunchMode介绍
standard模式
- 默认启动模式,每次启动都会新建Activity实例,并入任务栈顶
- 适用于相互独立的页面
singleTop模式
- 栈顶模式
- 若启动的Activity已位于栈顶,则只回调onNewIntent,否则创建新Activity实例并入栈
- 适用于保持单一实例的页面,避免重复创建
例:用于通知详情页,当有多个通知时,无需为每个通知单独开启Activity
singleTask模式
- 单任务栈模式(单例)
- 若启动的Activity已位于栈中,则只回调
onNewIntent并将其上的Activity实例移出任务栈,使其回至栈顶,否则新建Activity实例并入栈 - 适用于音乐播放界面,确保只有一个播放界面
- 适用于程序入口页面,确保整个应用只有一个首页Activity实例
例:浏览器主界面,无论多少应用打开浏览器都只会启动一个Activity实例,其余都在onNewIntent,并清空之前页面
singleInstance模式
- 单例模式
- 新任务栈中启动Activity,独占一个新的任务栈
- 一旦存在该Activity实例,任何应用再次启动该Activity,都只回调onNewIntent
- 效果与多个应用共享一个应用类似,无论哪个应用激活该Activity,都相当于进入共享应用中
- 适用于全局单例的功能,与其他应用不共享任务栈
例:闹钟提醒,闹钟提醒可能会不定时被启动,所以单独存在一个栈中比较合适
LaunchMode常见问题
- 如何在不同的任务栈中启动Activity?
- 可通过设置Intent的FLAG_ACTIVITY_NEW_TASK标志位,在新任务栈启动Activity,
若Activity已存在于其他任务栈,系统会将其移至新任务栈
val intent = Intent(this, DemoActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
- LauchMode与Intent搭配使用时如何正确处理传输数据?
- 使用Bundle传递数据。将数据封装至Bundle中,通过Intent传递,即使Activity被系统回收重建,也可保证数据恢复
- 序列化对象。传递自定义对象,需实现序列化
Serializable或Parcelable,以便在不同实例间传递 singleTask和singleTop模式需特别注意,在onNewIntent中处理singleInstance模式需特别注意,独立任务栈,可使用广播或共享文件通信
- 如何使用LaunchMode实现应用内导航?
- 关注点:
singleTop与parentActivityName - 子Activity启动模式设为singleTop,并通过parentActivityName属性指定父Activity
- 父Activity启动模式为standard
- 此时子Activity点击返回键,会跳转至父Activity
- 如何使用LaunchMode实现Activity单例?
- 可使用
singleInstance或singleTask实现 - singleInstance会创建新任务栈,并成为任务栈的根Activity,再次启动移至任务栈前台,并执行onNewIntent
- singleTask + taskAffinity属性,会创建新任务栈,并成为任务栈的根Activity,再次启动移至任务栈前台,并执行
onNewIntent
- LaunchMode与taskAffinity属性关系?
- taskAffinity属性可用来指定Activity所属的任务栈
- taskAffinity属性未配置,默认栈为应用包名
- taskAffinity指定栈存在,Activity添加至该任务栈
- taskAffinity指定栈不存在,创建栈并将Activity添加至该任务栈
- LaunchMode与taskAffinity共同决定Activity启动行为
例:LaunchMode为singleTask且taskAffinity与另一个Activity的taskAffinity相同时,该Activity启动时会将任务栈移至前台,并执行onNewIntent
- LaunchMode与Intent Flags如何巧妙搭配使用?
- 使用FLAG_ACTIVITY_NEW_TASK可在新任务栈启动
- 使用FLAG_ACTIVITY_CLEAR_TOP可清除该Activity上面的Activity
- 使用FLAG_ACTIVITY_CLEAR_TASK可清除任务栈所有Activity,实现
回到主页或重新登录功能 - singleTask + FLAG_ACTIVITY_NEW_TASK可创建新任务栈,可通过设置taskAffinity更加灵活的控制任务栈
- LaunchMode与FLAG_ACTIVITY_NEW_TASK有何区别?
- LaunchMode用来指定Activity的启动模式
- LaunchMode属于全局属性,对所有启动该Activity的Intent都有效
- FLAG_ACTIVITY_NEW_TASK是Intent的标志位,指定是否在新任务栈中打开
- LAG_ACTIVITY_NEW_TASK属于单次设置,只对当前启动Activity的Intent有效
- LaunchMode安全性问题如何预防?
- 避免
singleTask和singInstance模式下存储敏感信息,该实例可被多个任务或应用共享 - 增加
Intent数据验证,避免被恶意应用利用,尤其是FLAG_ACTIVITY_NEW_TASK等Flag使用时