十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
欢迎访问我的个人博客 传送门
10年积累的成都网站制作、成都网站建设、外贸营销网站建设经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先网站制作后付款的网站建设流程,更有大安免费网站建设让你可以放心的选择与我们合作。
应用通常包含多个 Activity ,每个 Activity 均应围绕用户可以执行的特定操作设计,并且能够启动其他 Activity,一个 Activity 可以启动设备上其他应用中的 Activity,即使两个 Activity 可能来自不同的应用,但是 Android 仍会将 Activity 保留在相同的任务中,以维护这种无缝的用户体验。这里所说的任务
就是指在执行特定作业时与用户交互的一系列 Activity,这些 Activity 按照各自的打开顺序排列在堆栈
(即返回栈)中。返回栈
以“后进先出”对象结构运行,如下图
如果要查看 Activity Task栈的情况,可以在命令行用 adb 命令查看
adb shell dumpsys activity activities
执行命令会出现很长一段详细信息 找到 Running activities
即可查看,如下图
在了解了任务和返回栈后,我们来说说启动模式,上图的堆栈是比较常规的,如果我们一直启动同一个 Activity 系统会重复创建多个实例,但这不是我们想要的结果。这时候为了满足我们的需求就需要使用 Android 提供的启动模式来修改系统的默认行为。目前有四种启动模式:standard、singleTop、singleTask 和 singleInstance。在 AndroidManifest.xml 中配置即可,如下:
系统在启动 Activity 的任务中创建 Activity 的新实例并向其传送 Intent。Activity 可以多次实例化,不管这个实例是否已经存在,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。这种模式的 Activity 被创建时它的 onCreate、onStart 都会被调用。这是一种典型的多实例实现,一个任务栈中可以有多个实例,每个实例也可以属于不同的任务栈。在这种模式下,谁启动了这个 Activity,那么这个 Activity 就运行在启动它的那个 Activity 所在的栈中。
这里通过简单的代码来验证,先实现方法来打印 Activity 的生命周期调用过程和 Taskid
fun printTaskInfo(activity: Activity, methodName: String) {
log("${activity.localClassName} $methodName taskId = ${activity.taskId}")
}
fun log(message: String, tag: String = "debugLog") {
Log.i(tag, message)
}
/**
* @param T 目标 Activity
*/
inline fun Context.toActivity() {
startActivity(Intent(this, T::class.java))
}
界面很简单就一个按钮,就不截图了,Activity 代码
class A : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_a)
printTaskInfo(this,"onCreate")
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
printTaskInfo(this,"onNewIntent")
}
override fun onStart() {
super.onStart()
printTaskInfo(this,"onStart")
}
fun click(view: View?) {
toActivity()
}
}
01-02 22:07:00.330 28281-28281/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 44
01-02 22:07:00.332 28281-28281/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 44
01-02 22:07:01.580 28281-28281/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 44
01-02 22:07:01.582 28281-28281/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 44
01-02 22:07:02.325 28281-28281/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 44
01-02 22:07:02.327 28281-28281/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 44
使用 adb 命令查看 Activity Task 栈,可以看出每启动一次 A 都会创建一次实例,不管这个实例是否已经存在
这里我们新建一个 Activity B ,调用 Activity 流程 :A - A - B - A
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_a) printTaskInfo(this, "onCreate") } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) printTaskInfo(this, "onNewIntent") } override fun onStart() { super.onStart() printTaskInfo(this, "onStart") } fun click(view: View?) { when (view?.id) { R.id.bt_toA -> toActivity
() R.id.bt_toB -> toActivity() else -> { } } }
01-02 22:15:18.399 28530-28530/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 45
01-02 22:15:18.400 28530-28530/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 45
01-02 22:15:21.229 28530-28530/com.will.testdemo I/debugLog: launchmode.A onNewIntent taskId = 45
01-02 22:15:24.927 28530-28530/com.will.testdemo I/debugLog: launchmode.B onCreate taskId = 45
01-02 22:15:24.929 28530-28530/com.will.testdemo I/debugLog: launchmode.B onStart taskId = 45
01-02 22:15:26.449 28530-28530/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 45
01-02 22:15:26.450 28530-28530/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 45
可以看出当 A 在当前栈顶的时候没有创建新的实例,并调用 onNewIntent 方法,没有调用 onCreate 和 onStart 方法
关于上文中所说的想要的任务栈
,指的是 taskAffinity 属性,手动设置所需的任务栈,这个后面会具体介绍
调用 Activity 流程 依旧是:A - A - B - A
打印日志:
01-02 22:25:59.608 24498-24498/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 54
01-02 22:25:59.611 24498-24498/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 54
01-02 22:26:02.844 24498-24498/com.will.testdemo I/debugLog: launchmode.A onNewIntent taskId = 54
01-02 22:26:05.753 24498-24498/com.will.testdemo I/debugLog: launchmode.B onCreate taskId = 54
01-02 22:26:05.758 24498-24498/com.will.testdemo I/debugLog: launchmode.B onStart taskId = 54
01-02 22:26:07.040 24498-24498/com.will.testdemo I/debugLog: launchmode.A onNewIntent taskId = 54
01-02 22:26:07.047 24498-24498/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 54
纳尼 Activity B 呢 怎么不见了,这是什么鬼操作,原来是 singleTask 默认有 clearTop 的效果,会导致栈内所有在它上面的 Activity 全部出栈
,这点一定不要忽略了
调用 Activity 流程 :A - B - B - A
,这次把 B 的启动模式设置为 singleInstance
01-02 22:41:59.069 305-305/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 57
01-02 22:41:59.071 305-305/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 57
01-02 22:42:00.280 305-305/com.will.testdemo I/debugLog: launchmode.B onCreate taskId = 58
01-02 22:42:00.283 305-305/com.will.testdemo I/debugLog: launchmode.B onStart taskId = 58
01-02 22:42:02.340 305-305/com.will.testdemo I/debugLog: launchmode.B onNewIntent taskId = 58
01-02 22:42:03.658 305-305/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 57
01-02 22:42:03.659 305-305/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 57
与 singleTask 结合使用,调用 Activity 流程:A - B - B - A - B
,设置 B 的启动模式为 singleTask ,并设置 taskAffinity
01-02 23:13:29.179 16793-16793/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 59
01-02 23:13:29.180 16793-16793/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 59
01-02 23:13:31.800 16793-16793/com.will.testdemo I/debugLog: launchmode.B onCreate taskId = 60
01-02 23:13:31.801 16793-16793/com.will.testdemo I/debugLog: launchmode.B onStart taskId = 60
01-02 23:13:33.740 16793-16793/com.will.testdemo I/debugLog: launchmode.B onNewIntent taskId = 60
01-02 23:13:34.928 16793-16793/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 60
01-02 23:13:34.931 16793-16793/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 60
01-02 23:13:36.203 16793-16793/com.will.testdemo I/debugLog: launchmode.B onNewIntent taskId = 60
01-02 23:13:36.204 16793-16793/com.will.testdemo I/debugLog: launchmode.B onStart taskId = 60
launchMode | 使用场景 |
---|---|
singleTop | 适合启动同类型的 Activity,例如接收通知启动的内容显示页面 |
singleTask | 适合作为程序入口 |
singleInstance | 适合需要与程序分离开的页面,例如闹铃的响铃界面 |