Activity启动流程要点
一、Activity启动流程
- Activity的启动流程一般是通过调用startActivity或者是startActivityForResult来开始的
- startActivity内部也是通过调用startActivityForResult来启动Activity,只不过传递的requestCode小于0
- Activity的启动流程涉及到多个进程之间的通讯这里主要是ActivityThread与ActivityManagerService之间的通讯
- ActivityThread向ActivityManagerService传递进程间消息通过ActivityManagerNative,ActivityManagerService向ActivityThread进程间传递消息通过IApplicationThread。
- ActivityManagerService接收到应用进程创建Activity的请求之后会执行初始化操作,解析启动模式,保存请求信息等一系列操作。
- ActivityManagerService保存完请求信息之后会将当前系统栈顶的Activity执行onPause操作,并且IApplication进程间通讯告诉应用程序继承执行当前栈顶的Activity的onPause方法;(A到B界面,打开B那么A得先Pause)
- ActivityThread接收到SystemServer的消息之后会统一交个自身定义的Handler对象处理分发;
- ActivityThread执行完栈顶的Activity的onPause方法之后会通过ActivityManagerNative执行进程间通讯告诉ActivityManagerService,栈顶Actiity已经执行完成onPause方法,继续执行后续操作;
- ActivityManagerService会继续执行启动Activity的逻辑,这时候会判断需要启动的Activity所属的应用进程是否已经启动,若没有启动则首先会启动这个Activity的应用程序进程(毕竟可以多进程);
- ActivityManagerService会通过socket与Zygote继承通讯,并告知Zygote进程fork出一个新的应用程序进程,然后执行ActivityThread的main()方法;
- 在ActivityThread.main方法中执行初始化操作,初始化主线程异步消息,然后通知ActivityManagerService执行进程初始化操作;
- ActivityManagerService会在执行初始化操作的同时检测当前进程是否有需要创建的Activity对象,若有的话,则执行创建操作;
- ActivityManagerService将执行创建Activity的通知告知ActivityThread,然后通过反射机制创建出Activity对象,并执行Activity的onCreate方法,onStart方法,onResume方法;
- ActivityThread执行完成onResume方法之后告知ActivityManagerService onResume执行完成(新界面展示),开始执行栈顶Activity的onStop方法(这个老界面即将走入后台,新界面马上展示);
- ActivityManagerService开始执行栈顶的onStop方法并告知ActivityThread;
- ActivityThread执行真正的onStop方法(A调用stop)
二、Activity布局创建流程
主要代码:
@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//Activity.onCreatesetContentView(R.layout.activity_main);
}
- 当ActivityManagerService接收到启动Activity的请求之后会通过IApplicationThread进程间通讯告知ApplicationThread并执行handleLauncherActivity方法;
- handleLauncherActivity方法内部调用了performLaunchActivity方法;
- performLaunchActivity方法里通过反射的机制创建的Activity,并调用了Activity的attach方法;
- 初始化了一些Activity的成员变量,主要是mWindow对象,并且mWindow的成员实例是PhoneWindow实例;
- performLaunchActivity调用mInstrumentation.callActivityOnCreate(activity, r.state);在里面调用performCreate方法,方法里实现onCreate的回调。从这儿开始走到OnCrete方法。
- 那么来第一行,super.onCreate()里面主要就是做一个初始化,并且之后会执行一个判断逻辑,若Activity的mCalled为false,则会抛出我们刚刚捕获的异常,那么这个mCalled成员变量是在什么时候被赋值的呢?好吧,就是在Activity的onCreate方法赋值的,所以我们在实现自己的Activity的时候只有调用了super.onCreate方法才不会抛出这个异常,反过来说,我们实现自己的Actiivty,那么一定要在onCreate方法中调用super.onCreate方法。
- 接下来是setContentView()方法。
public void setContentView(@LayoutRes int layoutResID) {getWindow().setContentView(layoutResID);initWindowDecorActionBar(); }
这个getWindow就是phoneWindow,在activity.attach初始化的
phoneWindow.setContentView--->installerDector()--->执行mDecor = generateDecor();生成一个DecorView。判断mContentParent(此处第一次为空)
if (mContentParent == null) {mContentParent = generateLayout(mDecor);}调用此方法
- generateLayout()方法里通过调用LayoutInflater.inflate方法来加载布局文件到内存中,关于LayoutInflater.inflater是如何加载布局文件的,并且,通过对代码的分析,我们发现PhoneWindow中的几个成员变量:mDector,mContentRoot,mContentParent的关系mDector --> mContentRoot --> mContentParent(包含)
- activity到phonewidow再到mDector --> mContentRoot --> mContentParent,activity就拥有了布局文件的引用
知识点:
- Activity的展示界面的特性是通过Window对象来控制的;
- 每个Activity对象都对应这个一个Window对象,并且Window对象的初始化在启动Activity的时候完成,在执行Activity的onCreate方法之前;
- 每个Window对象内部都存在一个FrameLayout类型的mDector对象,它是Acitivty界面的root view;
- Activity中的window对象的实例是PhoneWindow对象,PhoneWindow对象中的几个成员变量mDector,mContentRoot,mContentParent都是View组件,它们的关系是:mDector --> mContentRoot --> mContentParent --> 自定义layoutView
- LayoutInflater.inflate主要用于将布局文件加载到内存View组件中,也可以设定加载到某一个父组件中;
- 典型的Activity的onCreate方法中需要调用super.onCreate方法和setContentView方法,若不调用super.onCreate方法,执行启动该Activity的逻辑会报错,若不执行setContentView的方法,该Activity只会显示一个空页面。
三、Activity的布局绘制流程
从AMS调Activity的onResume到App进程的主线程,有关Activity onResume生命周期的第一个方法就是handleResumeActivity,mWindowManager是在Activity的attach方法中被创建的 ,在获取了Activity的Window相关参数之后执行了r.activity.makeVisible()方法。
//ActivityService.java
@Overridepublic void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,String reason) {......//1.最后会调到Activity的onResumefinal ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason); ......final Activity a = r.activity;......boolean willBeVisible = !a.mStartedActivity;if (!willBeVisible) {try {willBeVisible = ActivityManager.getService().willActivityBeVisible(a.getActivityToken());} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}if (r.window == null && !a.mFinished && willBeVisible) {r.window = r.activity.getWindow();View decor = r.window.getDecorView();decor.setVisibility(View.INVISIBLE);2.获取WindowManagerImpl对象ViewManager wm = a.getWindowManager();WindowManager.LayoutParams l = r.window.getAttributes();a.mDecor = decor;l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;l.softInputMode |= forwardBit;if (r.mPreserveWindow) {a.mWindowAdded = true;r.mPreserveWindow = false;ViewRootImpl impl = decor.getViewRootImpl();if (impl != null) {impl.notifyChildRebuilt();}}if (a.mVisibleFromClient) {if (!a.mWindowAdded) {a.mWindowAdded = true;3.调用WindowManagerImpl的addView方法wm.addView(decor, l);} ......}if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {r.activity.mVisibleFromServer = true;mNumVisibleActivities++;if (r.activity.mVisibleFromClient) {r.activity.makeVisible();}}......}.......}
Activity执行onResume之后再ActivityThread中执行Activity的makeVisible方法。
-
//Activity.java void makeVisible() {if (!mWindowAdded) {ViewManager wm = getWindowManager();//这里的ViewManager对象是通过getWindowManager()方法获取的。是在Activity的attach方法方法中初始化的wm.addView(mDecor, getWindow().getAttributes());mWindowAdded = true;}mDecor.setVisibility(View.VISIBLE);//将mDecor给显示到界面上 }
-
wm.addView(mDecor, getWindow().getAttributes()); addView这里面调用了mGlobal.addView(view, params, mDisplay, mParentWindow);而mGlobal为WindowManagerGlobal,在mGlobal.addView里调用了root.setView。(ViewRootImpl)
-
在root.setView里调用了调用了requestLayout方法,调用执行重绘的请求
-
@Override public void requestLayout() {if (!mHandlingLayoutInLayoutRequest) {checkThread();//检查是否UI线程mLayoutRequested = true;scheduleTraversals(); 这里面调用performTraversals方法, 从这个方法开始我们的View经过大小测量,位置测量, 界面绘制三个逻辑操作之后就可以展示在界面中了。} }
-
performTraversals的相关内容如下(绘制界面)
-
View的绘制流程包含了测量大小,测量位置,绘制三个流程;
-
Activity的界面绘制是从mDecor即根View开始的,也就是从mDecor的测量大小,测量位置,绘制三个流程;
-
View体系的绘制流程是从ViewRootImpl的performTraversals方法开始的;
-
View的测量大小流程:performMeasure --> measure --> onMeasure等方法;
-
View的测量位置流程:performLayout --> layout --> onLayout等方法;
-
View的绘制流程:onDraw等方法;
-
View组件的绘制流程会在onMeasure,onLayout以及onDraw方法中执行分发逻辑,也就是在onMeasure同时执行子View的测量大小逻辑,在onLayout中同时执行子View的测量位置逻辑,在onDraw中同时执行子View的绘制逻辑;
-
Activity中都对应这个一个Window对象,而每一个Window对象都对应着一个新的WindowManager对象(WindowManagerImpl实例);
相关文章:
Activity启动流程要点
一、Activity启动流程 Activity的启动流程一般是通过调用startActivity或者是startActivityForResult来开始的startActivity内部也是通过调用startActivityForResult来启动Activity,只不过传递的requestCode小于0Activity的启动流程涉及到多个进程之间的通讯这里主…...

lua 计算第几周
需求 计算当前赛季的开始和结束日期,2024年1月1日周一是第1周的开始,每两周是一个赛季。 lua代码 没有处理时区问题 local const 24 * 60 * 60 --一整天的时间戳 local server_time 1716595200--todo:修改服务器时间 local date os.date("*t…...

负载均衡策略
...

海外网红营销新趋势:“快闪式”营销如何迅速提升品牌曝光度
在当今数字化时代,海外网红营销已成为品牌迅速触达全球消费者、提升品牌曝光度和刺激销售的重要手段。其中,“快闪式”营销以其独特的时效性、创意性和互动性,成为品牌与海外网红合作的新趋势。本文Nox聚星将和大家探讨如何利用海外网红的影响…...

速看!打造专属数字化能力模型的七大关键!
在数字化浪潮中,企业如何打造适应自身发展的数字化能力模型?这是许多企业面临的重要课题。今天,通过众多企业使用蚓链数字化生态解决方案实践总结,为大家分享至关重要的七大经验,助你开启数字化转型之旅! 1…...

青蛙跳台阶问题
本期介绍🍖 主要介绍:青蛙跳台阶问题,青蛙跳台阶与斐波那契数列的关系👀。 文章目录 1. 题目2. 递归解题思路3. 迭代解题思路 1. 题目 从前有一只青蛙他想跳台阶,有n级台阶,青蛙一次可以跳1级台阶ÿ…...
linux日常运维2
下载linux离线安装包---- 利用 Downloadonly 插件下载 RPM 软件包及其所有依赖包 1. 先找个可以上网的linux操作系统,这里是以centos7操作系统为例,如果要使用centos6就先安装一个centos6的系统,然后让他可以上网,后面步骤如下 a.…...

flink cdc mysql整理与总结
文章目录 一、业务中常见的需要数据同步的场景CDC是什么FlinkCDC是什么CDC原理为什么是FlinkCDC业务场景flink cdc对应flink的版本 二、模拟案例1.阿里云flink sql2.开源flink sql(单机模式)flink 安装安装mysql3.flink datastream 三、总结 提示:以下是本篇文章正文…...

【三维重建】ePnP
PnP问题应用与一下场景: 已知三维点和对应二维点以及相机相机内参数,可以获取相机外参。 我们介绍其中的一种算法:ePnP 算法流程 1、ePnP算法首先在世界坐标系内寻找4个控制点,记作 C 1 w , C 2 w , C 3 w , C 4 w C_1^w,C_2^w,…...

C++进阶之路:何为运算符重载、赋值运算符重载与前后置++重载(类与对象_中篇)
✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…...

8、python基础知识图谱
...

智慧校园建设规划方案
在信息化浪潮的推动下,智慧校园的建设已成为教育现代化的必然趋势。以创新科技赋能教育,打造智慧校园,旨在提升教学品质,优化管理流程,增强学生体验。构建智慧校园需要具有前瞻性的规划方案,它将以教育为核…...

【深度学习实战—8】:基于MediaPipe的人脸检测
✨博客主页:王乐予🎈 ✨年轻人要:Living for the moment(活在当下)!💪 🏆推荐专栏:【图像处理】【千锤百炼Python】【深度学习】【排序算法】 目录 😺一、Med…...

OSCP学习,布置你的Kali Linux
为什么要写这篇文章? 我是一个OSCP学习者,以教促学。同时也能让各位入门的师傅们更好的了解OSCP这门课程。本人文笔不太好,如果有什么写的不对的地方,师傅们多多指正。 参考资料: OSCP 考试电子书 Linux Basics for…...
PWA离线优先策略:提升用户体验的关键步骤
Progressive Web Apps (PWA) 的离线优先策略是通过Service Worker和Cache API实现的,它允许在没有网络连接时仍然可以访问网站的部分或全部内容。 2500G计算机入门到高级架构师开发资料超级大礼包免费送! 1. 创建Service Worker注册文件(se…...

网页提示“非私密连接”是为什么?
网页提示“非私密连接”(英文提示可能是 "Your connection is not private" 或 "Your connection is not secure")主要是因为浏览器无法验证你正试图访问的网站的SSL/TLS证书,或者是证书存在问题,从而无法建立…...

[自动驾驶技术]-8 Tesla自动驾驶方案之硬件(AI Day 2022)
特斯拉在AI Day 2022先介绍了AI编译器,后面又介绍了Dojo的硬件软件,软件部分和AI编译器有部分重叠,本文介绍还是延用AI Day的思路,分为三部分:AI编译和推理,Dojo硬件,Dojo软件。 特斯拉车道检测…...

人力资源管理信息化系统如何支持企业开展管理诊断?
华恒智信人力资源顾问有限公司致力于帮助企业开展人力资源管理方面的各项提升改进工作,在长期的咨询工作中,最常听到企业提到的问题莫过于管理诊断方面的问题,事实上,很多企业在日常工作中,都意识到企业内部存在管理方…...

Cohere继Command-R+之后发布大模型Aya-23,性能超越 Gemma、Mistral 等,支持中文
前言 近年来,多语言大模型(MLLM)发展迅速,但大多数模型的性能依然存在显著差距,尤其是在非英语语言方面表现不佳。为了推动多语言自然语言处理技术的发展,Cohere团队发布了新的多语言指令微调模型家族——…...

身为UI设计老鸟,不学点3D,好像要被潮流抛弃啦,卷起来吧。
当前3D原则在UI设计中运用的越来越多,在UI设计中,使用3D元素可以为界面带来以下几个价值: 增强视觉冲击力:3D元素可以通过立体感和逼真的效果,为界面增添视觉冲击力,使得设计更加生动、吸引人,并…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
从零手写Java版本的LSM Tree (一):LSM Tree 概述
🔥 推荐一个高质量的Java LSM Tree开源项目! https://github.com/brianxiadong/java-lsm-tree java-lsm-tree 是一个从零实现的Log-Structured Merge Tree,专为高并发写入场景设计。 核心亮点: ⚡ 极致性能:写入速度超…...