Activity 启动后流程分析

发布于 2024-05-23 12:57:31 字数 4217 浏览 24 评论 0

启动流程

App 发起进程:从桌面启动应用,则发起的进程即为 Launcher 所在的进程。从某 App 应用内启动远程的进程,则发送的进程即为该 App 所在的进程。发送进程先通过 binder 发送消息给 system_server 进程。

system_server 进程:调用 Process.Start() 方法,通过 socket 向 Zygote 进程发送创建新进程的请求。

zygote 进程:在执行 ZygoteInit.main() 后便进入 runSelectLoop() 循环体内,当有客户端连接时便会执行 ZygoteConnection.runOnce() 方法,再经过层层调用后 fork 出新的应用进程

新进程:执行 handleChildProc 方法,最后调用 ActivityThread.main() 方法

进程创建的流程图如下:

线程启动

Activity 启动流程

Activity 启动时序图

LaunchMode

standard 是 Activity 默认的启动模式,在不进行显式指定的情况下,所有活动都会自动使用这种启动模式。
每次都会启动一个新的 Activity 放到栈顶 android:launchMode="standard" ,此时每次点击按钮都会创建新的 Activity 实例

代码示例:


点击三次,输出的都是不同的 Activity 实例:

singleTop:当 Activity 的启动模式是 singleTop 时,如果要启动的 Activity 已经处于栈顶,则直接使用,不会再创建新的实例(核心是位于栈顶才会被复用)会回调 onNewIntent 方法  android:launchMode="singleTop"

代码示例:


点击 MainActivity 的 button1,点击多次日志也只会打出一条,也就是说在 singleTop 启动模式下,由于要启动的 MainActivity 实例已经在栈顶,所以不会重新创建,只会存在一个实例,表现上也不会出现 standard 模式下的跳转;点击 MainActivity 的 button2,会跳转到 FirstActivity,这时会创建 FirstActivity 实例并入栈,这时候继续点击 FirstActivity 的按钮 button,会重新创建 MainActivity 实例,因为此时栈顶已经是 FirstActivity 了。

分析:singleTop 适用的场景,通常比较适用于接收到消息后显示的界面。比如 qq 接收消息弹出 Activity 消息界面,需要用一个 activity 实例来展示。还有新闻消息的推送之类的。

singleTask:当活动的启动模式为 singleTask 时,启动该 Activity 会现在栈中检查是否已存在,若存在则直接将该活动之上的 Activity 全部出栈。(跟 singleTop 比较相似,但是这个是用于检测整个栈里是否已经存在要启动的 Activity),也会回调 onNewIntent 方法 android:launchMode="singleTask" ​(设置 MainActivity 启动模式为 singleTask)

代码示例:

输出:

查看栈信息:

adb shell dumpsys activity activities

Activities=[ActivityRecord{d6e9fc6 u0 com.randy.launchapp/.MainActivity t4568}]

发现从 SecondActivity 跳转到 MainActivity 之后,Activity 栈中只存在 MainActivity 实例了,FirstActivity 和 SecondActivity 都被从栈里移除了。

分析:singleTask 模式比较适合应用的主界面 activity

singleInstance: 在 singleInstance 模式下,该 Activity 在整个 android 系统内存中有且只有一个实例,而且 该实例单独尊享一个 Task。换句话说,A 应用需要启动的 MainActivity 是 singleInstance 模式,当 A 启动后,系统会为它创建一个新的任务栈,然后 A 单独在这个新的任务栈中,如果此时 B 应用也要激活 MainActivity,由于栈内复用的特性,则不会重新创建,而是两个应用共享一个 Activity 的实例

启动方式的设置

  • 通过 AndroidMenifest.xml 文件为 Activity 指定启动模式
  • 通过在 Intent 中设置标志位(addFlags 方法) 来为 Activity 指定启动模式
Intent intent = new Intent();
intent.setClass(ActivityB.this,ActivityA.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
  • Intent.FLAG_ACTIVITY_NEW_TASK -- singleTask
  • Intent.FLAG_ACTIVITY_SINGLE_TOP -- singleTop
  • Intent.FLAG_ACTIVITY_CLEAR_TOP -- singleTask
  • Intent.FLAG_ACTIVITY_NO_HISTORY -- 使用该模式来启动 Activity,当该 Activity 启动其他 Activity 后,该 Activity 就被销毁了,不会保留在任务栈中。如 A-B,B 中以这种模式启动 C,C 再启动 D,则任务栈只有 ABD
  • Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS -- 使用该标识位启动的 Activity 不添加到最近应用列表,也即我们从最近应用里面查看不到我们启动的这个 activity。与属性 android:excludeFromRecents="true" 效果相同

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

0 文章
0 评论
23 人气
更多

推荐作者

玍銹的英雄夢

文章 0 评论 0

我不会写诗

文章 0 评论 0

十六岁半

文章 0 评论 0

浸婚纱

文章 0 评论 0

qq_kJ6XkX

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文