再谈启动一个Activity大致时序图

太多了,笔者不想写,

读者可通过PlantUML插件查看如下PUML文件生成的时序图。

补充说明下,Android31版本。

@startuml
'https://plantuml.com/sequence-diagram
skinparam dpi 800
scale 15000 width
scale 5000 heightautonumber
==Launcher==
Launcher -> Activity:startActivity(intent)
Activity->Activity:startActivity(intent,bundle)
Activity->Activity:startActivityForResult
Activity->Instrumentation:execStartActivity
note left
activity通过调用内部成员
mInstrumentation与atms
交互,即将开始进入系统进程
end note
Instrumentation->ActivityTaskManagerService.Stub:startActivity
==SystemService==
ActivityTaskManagerService.Stub->ActivityTaskManagerService:StartActivity
ActivityTaskManagerService->ActivityTaskManagerService:startActivityAsUser
ActivityTaskManagerService->ActivityTaskManagerService:startActivityAsUser
ActivityTaskManagerService->ActivityStarter:execute
ActivityStarter->ActivityStarter:executeRequest
note left
这里,会验证启动参数的合法性,
随后,创建一个ActivityRecord
作为一个Activity的唯一存在标识
end note
ActivityStarter->ActivityStarter:startActivityUnchecked
ActivityStarter->ActivityStarter:startActivityInner
note left
此函数的功能,如果没有Stack,就要新创建一个Stack,
也就是ActivityStack,保存到mTargetTask中,
通过setNewTask将待启动的ActivityRecord
和新创建的Stack绑定,并且将其置于Stack Top,
see ActivityStack::startActivityLocked()
see ActivityStack::moveToFront()
end note
ActivityStarter->ActivityStack:startActivityLocked
note left
这就是绑定ActivityRecord和新创建的Stack(Task)
end noteActivityStack->RootWindowContainer:resumeFocusedStacksTopActivities
note left
对于新启动的Activity,走此分支
end noteRootWindowContainer->ActivityStack:resumeTopActivityUncheckedLocked
note left
此ActivityStack是13步新创建的,
开始调度Activity
end noteActivityStack->ActivityStack:resumeTopActivityInnerLockednote left
这一步很关键,因为要Resume即将启动的Activity,
那么,首先要检查即将启动的Activity在没在栈顶,
如果不在,就要去pause栈顶的Activity
end note
ActivityStack->TaskDisplayArea:pauseBackStacks
note left
这里返回是否在pause栈顶的Activity,
一般这里会返回true,因为需要pause Launcher,
传入next参数即topRunningActivity
end notenote right
逻辑是去topStack中去判断是否有可见Activity,
如果有则pause掉,否则返回false,
end note
TaskDisplayArea->ActivityStack:startPausingLocked
note right
开始pause Launcher,
通过mAtmService(ATMS)获取生命周期管理,
执行生命周期PauseActivityItem事务
end note
ActivityStack->ClientLifecycleManager:scheduleTransactionnote left
注意,这里传的参数有PauseActivityItem
end note
ClientLifecycleManager->ClientLifecycleManager:scheduleTransaction
ClientLifecycleManager->ClientTransaction:schedule
ClientTransaction->IApplicationThread:scheduleTransaction
note right
进入Launcher进程,去执行Pause事务
end noteTaskDisplayArea-->ActivityStack:pauseBackStacks:true
ActivityStack-->RootWindowContainer:resumeTopActivityInnerLocked:true
RootWindowContainer-->ActivityStarter:resumeTopActivityUncheckedLocked:true
ActivityStarter-->ActivityStarter:ActivityStarter:START_SUCCESS==Launcher进程==
IApplicationThread->ActivityThread:scheduleTransaction
ActivityThread->ActivityThread:sendMessage(159,transaction)
ActivityThread->Handler:sendMessage
note right
这里159代表事务EXECUTE_TRANSACTION
一顿Looper后可以直接看handleMessage处
end noteHandler->Handler:handleMessage
ActivityThread->TransactionExecutor:executeTransactionExecutor->TransactionExecutor:executeLifecycleState
TransactionExecutor->PauseActivityItem:execute
PauseActivityItem->ActivityThread:handlePauseActivity
note right
熟悉的ActivityThread,开始pause Activity
end noteActivityThread->ActivityThread:performPauseActivity
ActivityThread->ActivityThread:performPauseActivityIfNeeded
ActivityThread->Instrumentation:callActivityOnPause
Instrumentation->Activity:performPause
Activity->Activity:onPauseTransactionExecutor->PauseActivityItem:postExecute
PauseActivityItem->ActivityTaskManagerService.Stub:activityPaused
note left
通知系统进程,Launcher已经pause
end note
==SystemService==
ActivityTaskManagerService->ActivityRecord:activityPaused(false/*timeout*/)
note right
拓展:这里就是其中一种ANR,如果没超时就移除anr回调,
end note
ActivityRecord->ActivityStack:completePauseLocked(true/*resumeNext*/,null)
ActivityStack->RootWindowContainer:resumeFocusedStacksTopActivitiesRootWindowContainer->ActivityStack:resumeTopActivityUncheckedLockednote right
找到下一个即将启动的ActivityStack,开始Resume
end noteActivityStack->ActivityStack:resumeTopActivityInnerLockedActivityStack->TaskDisplayArea:pauseBackStacks
TaskDisplayArea-->ActivityStack:pauseBackStacks:falseActivityStack->ActivityStackSupervisor:startSpecificActivity
note right
这里通过ActivityRecord去获取WindowProcessController,
这个和进程相关,第一次启动肯定没有对应进程,那么就需要创建进程
end noteActivityStackSupervisor->ActivityTaskManagerService:startProcessAsync
ActivityTaskManagerService->ActivityManagerInternal:startProcess
note right
这里通过handler调用到此处,
ActivityManagerInternal是一个抽象类,
其此处实例是ActivityServiceManager的LocalService
end note
ActivityManagerInternal->ActivityManagerService:startProcessLocked
ActivityManagerService->ProcessList:startProcessLocked
ProcessList->ProcessList:startProcessLocked
ProcessList->ProcessList:startProcessLocked
ProcessList->ProcessList:startProcessLocked
ProcessList->ProcessList:startProcess
ProcessList->Process:start
Process->ZygoteProcess:start
ZygoteProcess->ZygoteProcess:startViaZygote
note right
写入参数,通过socket发送给Zygote
end note
ZygoteProcess->ZygoteProcess:zygoteSendArgsAndGetResult
ZygoteProcess->ZygoteProcess:attemptZygoteSendArgsAndGetResult
ZygoteProcess->ZygoteState:write
note right
正式发送给zygote
end note
ZygoteProcess->ZygoteState:read
note right
主动读取结果,获取新启动的进程pid,保存到上下文中,
等待attach新启动的进程,由此,我们进入Zygote进程
end note==Zygote==
ZygoteInit->ZygoteInit:main
ZygoteInit->ZygoteServer:runSelectLoop
ZygoteServer->ZygoteConnection:processOneCommand
ZygoteConnection->Zygote:forkAndSpecialize
note right
这个返回值很关键,如果在此处将fork出两个进程,
如果是新创建的进程,pid为0,否则就是Zygote进程
end noteZygote-->ZygoteConnection:pid
ZygoteConnection->ZygoteConnection:handleParentProc
ZygoteConnection->ZygoteState:write
note right
写入新创建的pid给SystemService
end note
ZygoteConnection-->ZygoteServer:processOneCommand:Runnable
ZygoteServer->ZygoteServer:runSelectLoop
note right
继续监听其它连接,完毕
end note
==App进程==
Zygote-->ZygoteConnection:pid
ZygoteConnection->ZygoteConnection:handleChildProc
ZygoteConnection->closeSocket
ZygoteConnection->ZygoteInit:childZygoteInit
ZygoteInit->RuntimeInit:findStaticMain
note right
这里找到ActivityThread.main()方法
end note
RuntimeInit-->ZygoteInit:main
RuntimeInit-->ZygoteConnection:main
ZygoteConnection-->ZygoteServer:main
ZygoteServer-->ZygoteInit:runSelectLoop:main
ZygoteInit->ActivityThread:main
note left
至此,app的入口正式启动,
这里负责创建Looper.prepare();
还有最重要的attach,毕竟刚创建的app是个新生儿,
需要把自己注册到android世界中,才能获得活动的权利
最后进入主线程死循环loop
end note
ActivityThread->ActivityThread:attach
ActivityThread->ActivityManagerService.Stub:attachApplication
==SystemService==
ActivityManagerService.Stub->ActivityManagerService:attachApplication
ActivityManagerService->ActivityManagerService:attachApplicationLocked
ActivityManagerService->ActivityTaskManagerInternal
note right
这个是ATMS的LocalService
end note
ActivityTaskManagerInternal->RootWindowContainer:attachApplication
RootWindowContainer->RootWindowContainer:startActivityForAttachedApplicationIfNeeded
RootWindowContainer->ActivityStackSupervisor:realStartActivityLocked
note left
现在进程有了,该真正启动了
end note
ActivityStackSupervisor->ClientLifecycleManager:scheduleTransaction
note right
这里面约莫842行,给事务添加了回调,LaunchActivityItem;
然后也设置的生命周期状态ResumeActivityItem
end note
ClientLifecycleManager->ClientTransaction:schedule
ClientTransaction->IApplicationThread:scheduleTransaction
==App进程==
IApplicationThread->ActivityThread:scheduleTransaction
ActivityThread->ActivityThread:sendMessage(159,transaction)
ActivityThread->Handler:sendMessage
Handler->TransactionExecutor:execute
TransactionExecutor->TransactionExecutor:executeCallbacks
note right
注意此处的LaunchActivityItem
end note
TransactionExecutor->LaunchActivityItem:execute
LaunchActivityItem->ActivityThread:handleLaunchActivity
ActivityThread->ActivityThread:performLaunchActivity
ActivityThread->Instrumentation:newActivity
Instrumentation-->ActivityThread:activity
ActivityThread->Activity:attachnote left
那么,activity就被反射创建了,
这里,创建了PhoneWindow等必要成员
end note
ActivityThread->Instrumentation:callActivityOnCreate
Instrumentation->Activity:performCreate
Activity->Activity:onCreate
Activity-->TransactionExecutor
TransactionExecutor->TransactionExecutor:executeLifecycleState
TransactionExecutor->TransactionExecutor:cycleToPath
note left
这样终态传入的是Resume,因此需要在此处拿到IntArray的生命周期表
end note
TransactionExecutor->TransactionExecutor:performLifecycleSequence
note left
挨个走start、resume,
end note
TransactionExecutor->ActivityThread:handleStartActivity
ActivityThread->Activity:performStart
Activity->Instrumentation:callActivityOnStart
Instrumentation->Activity:onStart
Activity-->TransactionExecutorTransactionExecutor->ActivityThread:handleResumeActivity
ActivityThread->Activity:performResume
Activity->Instrumentation:callActivityOnResume
Instrumentation->Activity:onResume
Activity-->ActivityThread:handleResumeActivity
note left
此处,继续走handlerResumeActivity接下来的分支,
就是绑定Activity和Window的过程,
wm.addView(decor, l);
自此就是View绘制流程(极多的另一流程),然后显示在屏幕上
end noteActivity-->ActivityThread:main
ActivityThread->Looper:loop
@enduml

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/654238.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IT界含金量高的证书,除了软考证书,还有这15种

文章目录 计算机技术与软件专业技术资格考试全国计算机信息高新技术考试思科认证微软认证:华为认证IBM认证国家信息安全水平考试注册信息安全专业人员注册信息安全渗透测试工程师项目管理专业人士资格认证Red Hat认证CompTIA 认证CISSP认证Oracle认证Sun认证AWS认证…

Redis的五种常用数据结构以及其底层实现

1.字符串 字符串作为Redis中最基础的数据结构,他存储的值可以是任何东西,可以是字符串,数字,二进制,但是字符串存储的值不能超过512M 在Redis中字符串的底层编码是根据值进行改变的 当存储的字符串是一个数字的时候…

MYSQL中group by分组查询的用法详解(where和having的区别)!

文章目录 前言一、数据准备二、使用实例1.如何显示每个部门的平均工资和最高工资2.显示每个部门的每种岗位的平均工资和最低工资3.显示平均工资低于2000的部门和它的平均工资4.having 和 where 的区别5.SQL查询中各个关键字的执行先后顺序 前言 在前面的文章中,我们…

什么是git,怎样下载安装?

简介: 应用场景: 应用场景:团队企业开发 作用: 安装: 1.网址:Git - Downloads 很卡很慢 2.可以选择镜像网站下载(推荐) CNPM Binaries Mirror

每日一题 力扣514自由之路

514. 自由之路 题目描述: 电子游戏“辐射4”中,任务 “通向自由” 要求玩家到达名为 “Freedom Trail Ring” 的金属表盘,并使用表盘拼写特定关键词才能开门。 给定一个字符串 ring ,表示刻在外环上的编码;给定另一…

WhisperBot:整合了Mistral大型语言模型的实时语音转文本系统

项目简介 欢迎来到 WhisperBot。WhisperBot 基于 WhisperLive 和 WhisperSpeech 的功能而构建,在实时语音到文本管道之上集成了大型语言模型 Mistral (LLM)。WhisperLive 依赖于 OpenAI Whisper,这是一个强大的自动语音识别 (ASR) 系统。Mistral 和 Whi…

企业中不同大数据迁移的区别是什么?

在大数据时代,企业面临着海量数据的管理、分析和应用挑战。为了克服数据存储、传输和处理中的难题,如数据量巨大、网络环境多变、存储成本高昂以及安全风险上升等,企业必须对数据进行备份、同步、分发或归档。这一过程中,数据的复…

STM32CubeMX教程31 USB_DEVICE - HID外设_模拟键盘或鼠标

目录 1、准备材料 2、实验目标 3、模拟鼠标实验流程 3.0、前提知识 3.1、CubeMX相关配置 3.1.0、工程基本配置 3.1.1、时钟树配置 3.1.2、外设参数配置 3.1.3、外设中断配置 3.2、生成代码 3.2.0、配置Project Manager页面 3.2.1、设初始化调用流程 3.2.2、外设中…

【C++】输入输出、缺省参数、函数重载

目录 C的输入和输出 缺省参数 概念 缺省参数的分类 全缺省参数 半缺省参数 函数重载 概念 C支持函数重载的原理--名字修饰 C的输入和输出 #include<iostream> // std是C标准库的命名空间名&#xff0c;C将标准库的定义实现都放到这个命名空间中 using namespace …

python基础之ORM操作Mysql数据库

首先简单介绍下SQLalchemy库和sqlacodegen库。 SQLalchemy 库是一个流行的 Python 数据库工具&#xff0c;用于与各种关系型数据库进行交互。它提供了一个统一的 API&#xff0c;使得开发人员可以使用相同的代码来操作不同的数据库&#xff0c;而无需关心数据库的具体细节。 …

【笔记】Helm-4 最佳实践-8 基于角色的访问控制

基于角色的访问控制 最佳实践的这部分讨论在chart清单中创建和格式化RBAC资源。 RBAC资源有&#xff1a; ServiceAccount(namespaced) Role(namespaced) ClusterRole RoleBinding(namespaced) ClusterRoleBinding YAML配置 RBAC和服务账户配置应该独立的key。它们是独立…

【WinRAR技巧】WinRAR整理密码是什么意思?

之前给大家介绍过WinRAR自动加密的设置方法&#xff0c;今天再介绍一种RAR压缩包加密方法&#xff1a;整理密码。 什么是整理密码&#xff1a; 在加密rar文件的时候&#xff0c;点击下拉框选择密码&#xff0c;不用输入密码 设置方法&#xff1a; 前面的操作步骤和设置自动…

ubuntu22.04@laptop安装配置VNC服务端

ubuntu22.04laptop安装&配置VNC服务端 1. 源由2. 系统安装3. VNC安装3.1 系统更新3.2 lightdm安装3.3 x11vnc安装3.4 x11vnc配置3.5 x11vnc自启动3.6 x11vnc状态查询 4. 演示视频 1. 源由 最近系统搞TensorFlow, OpenCV, Python&#xff0c;折腾各种环境&#xff0c;把系统…

GitLab升级16.8.0失败

漏扫报警Gitlab高危漏洞&#xff0c;于是立即升级。 yum命令提示有16.8.0可以升级&#xff0c;输入y 1G的软件包下载完毕&#xff0c;检测正常&#xff0c;安装软件包... 之后报错退出。 根据错误提示了解到由于上一次gitlab-ctl reconfigure执行失败导致执行升级程序退出。…

提升编程效率的利器: 解析Google Guava库之集合篇Table二维映射(四)

在Java开发中&#xff0c;我们经常使用Map数据结构来存储键值对&#xff0c;其中键是唯一的&#xff0c;可以快速查找到对应的值。但在某些场景下&#xff0c;我们可能需要一个更复杂的映射结构&#xff0c;其中键由两部分组成&#xff0c;类似于一个二维表格的行和列。Guava库…

自动化测试脚本编写(超详细)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 自动化测试脚本 什么是自动化测试&#xff1f; 自动化测试是验…

Spring Cloud + Vue前后端分离-第15章 课程总结

源代码在GitHub - 629y/course: Spring Cloud Vue前后端分离-在线课程 Spring Cloud Vue前后端分离-第15章 课程总结 重点难点梳理 环境的搭建 代码生成器 文件上传和视频播放 通用权限设计 学习技巧 养成做笔记的习惯 养成阶段性提交代码的习惯 问答区多交流

springboot 动态导出pdf

springboot 动态导出pdf 原理是通过freemarker插入数据到html模版里面&#xff0c;html你就叫前端帮你写好&#xff0c;他不写你就告诉你主管让他叫他写&#xff0c;你只管往预留的位置插入数据就行&#xff0c;然后通过itextpdf会将准备好html文件转成PDF。 ### 1、准备依赖 &…

思维题之T恤衫

[ABC332C] T-shirts - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 源于atcoder 由于字符串的长度为1000.不论怎样&#xff0c;顺序枚举即可。 import java.awt.FontFormatException; import java.awt.geom.AffineTransform; import java.awt.image.BandCombineOp; import …

自定义注解实现动态数据源

在Java开发中&#xff0c;使用多数据源能够提高系统的灵活性和性能。本文将通过介绍自定义注解的方式&#xff0c;实现动态数据源的切换。通过这种创新性的方法&#xff0c;开发者可以根据业务需求轻松切换数据库连接&#xff0c;实现数据源的动态管理&#xff0c;提升系统的可…