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);
}

  1.  当ActivityManagerService接收到启动Activity的请求之后会通过IApplicationThread进程间通讯告知ApplicationThread并执行handleLauncherActivity方法;
  2. handleLauncherActivity方法内部调用了performLaunchActivity方法;
  3. performLaunchActivity方法里通过反射的机制创建的Activity,并调用了Activity的attach方法;
    1. 初始化了一些Activity的成员变量,主要是mWindow对象,并且mWindow的成员实例是PhoneWindow实例;
  4. performLaunchActivity调用mInstrumentation.callActivityOnCreate(activity, r.state);在里面调用performCreate方法,方法里实现onCreate的回调。从这儿开始走到OnCrete方法。
  5. 那么来第一行,super.onCreate()里面主要就是做一个初始化,并且之后会执行一个判断逻辑,若Activity的mCalled为false,则会抛出我们刚刚捕获的异常,那么这个mCalled成员变量是在什么时候被赋值的呢?好吧,就是在Activity的onCreate方法赋值的,所以我们在实现自己的Activity的时候只有调用了super.onCreate方法才不会抛出这个异常,反过来说,我们实现自己的Actiivty,那么一定要在onCreate方法中调用super.onCreate方法。
  6. 接下来是setContentView()方法。
  7. public void setContentView(@LayoutRes int layoutResID) {getWindow().setContentView(layoutResID);initWindowDecorActionBar();
    }

    这个getWindow就是phoneWindow,在activity.attach初始化的

  8. phoneWindow.setContentView--->installerDector()--->执行mDecor = generateDecor();生成一个DecorView。判断mContentParent(此处第一次为空)

    if (mContentParent == null) {mContentParent = generateLayout(mDecor);}调用此方法
  9. generateLayout()方法里通过调用LayoutInflater.inflate方法来加载布局文件到内存中,关于LayoutInflater.inflater是如何加载布局文件的,并且,通过对代码的分析,我们发现PhoneWindow中的几个成员变量:mDector,mContentRoot,mContentParent的关系mDector --> mContentRoot --> mContentParent(包含)
  10. 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实例);

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

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

相关文章

vue 如果有某个子元素就给父元素加样式,或者通过子元素显示来判断父元素是否显示

有这样一个场景&#xff0c;父元素是一个 div&#xff0c;然后里边有多个子元素&#xff0c;同时父元素上添加了很多样式 需求是&#xff1a;如果有子元素&#xff0c;那么就显示父元素&#xff0c;如果没有一个子元素&#xff0c;则父元素也不显示 代码结构&#xff1a; <…

【vue-5】双向数据绑定v-model及修饰符

单向数据绑定&#xff1a;当数据发生改变时&#xff0c;视图会自动更新&#xff0c;但当用户手动更改input的值&#xff0c;数据不会自动更新&#xff1b; 双向数据绑定&#xff1a;当数据发生改变时&#xff0c;视图会自动更新&#xff0c;但当用户手动更改input的值&#xf…

鸿蒙原生应用元服务开发-WEB跨应用跳转

Web组件可以实现点击前端页面超链接跳转到其他应用。 在下面的示例中&#xff0c;点击call.html前端页面中的超连接&#xff0c;跳转到电话应用的拨号界面。 应用侧代码。 // xxx.ets import web_webview from ohos.web.webview; import call from ohos.telephony.call;Entr…

Vue基础(数据绑定、export使用)

1、简介 在使用vue开发的过程中&#xff0c;经常会遇到一些容易混淆的问题&#xff0c;因此&#xff0c;在本文中进行汇总操作&#xff0c;只有通过不断总结学习&#xff0c;才能更好掌握vue的使用&#xff08;每天进步一点&#xff09;。 2、数据绑定 在js中定义数据&#xf…

音乐编曲软件哪个好用 studio one和fl studio哪个好

编曲软件的出现&#xff0c;打破了时间与空间的限制&#xff0c;使得创作者能随时随地进行音乐创作。随着信息时代的发展&#xff0c;使用编曲软件进行音乐创作已经成为业界主流。业内常用的有Cubsae、LogicPro、Studio One、Ableton live等&#xff0c;这次教程我将为大家解读…

HTTP 协议的基本格式和Fidder的简单使用

HTTP协议诞生于1996&#xff08;开玩笑哈&#xff0c;诞生于1991年&#xff09;&#xff0c;http协议用于网页和手机app和服务器交互的场景。通过HTTP协议&#xff0c;客户端&#xff08;例如网页浏览器或手机应用&#xff09;可以向服务器发送请求&#xff0c;服务器则会响应这…

大数据开发面试题【Hadoop篇】

1、Hadoop特点 hadoop是一个分布式计算平台&#xff0c;能够允许使用编程模型在集群上对大型数据集进行分布式处理 hadoop的三大组件&#xff1a;HDFS&#xff08;分布式文件存储平台&#xff09;、MR&#xff08;计算引擎&#xff09;、YARN&#xff08;资源调度平台&#xf…

苹果手机突然白屏无反应怎么办?白屏修复办法分享!

苹果手机突然白屏无反应怎么办&#xff1f;下面小编就来给大家分享苹果手机突然白屏的原因和修复办法。 一般造成苹果手机出现白屏的原因如下&#xff1a; 系统问题&#xff1a;iOS系统的故障是导致苹果设备白屏无反应最常见的原因之一。例如&#xff0c;系统更新失败、应用冲…

TI_DSP_F2808学习笔记3: ePWM

共有6组ePWM&#xff0c;每一组 ePWM 模块都包含以下 7 个模块&#xff1a;时基模块 TB、计数比较模块 CC、动作模块 AQ、死区产生模块 DB、PWM 斩波模块 PC、错误联防模块 TZ、时间触发模块 ET。 时基模块 TB 确定PWM的周期和相位。 1&#xff09;PWM 时基计数器&#xff…

R18 NTN中的RACH-less HO

在看R18 38.300时,发现NTN场景 增加了如下黄色字体的内容,R18 NTN支持了RACH-less HO,索性就简单看了看。 NTN RACH less HO相关的描述主要在38.331,38.213和38.321中。38.300中的描述显示:网络侧会通过RRCReconfiguration消息将RACH-less HO相关的配置下发给UE, 其中会包…

【SpringCloud】负载均衡

目录 负载均衡什么是负载均衡生活场景为什么需要负载均衡负载均衡手段负载均衡总的来说有两种实现手段负载均衡具体可以通过多种手段来实现 SpringCloud中的负载均衡组件Ribbon VS Nginx负载均衡区别集中式LB进程内LB RibbonRibbon的工作原理Ribbon在工作时分成两步 使用1.提供…

光纤跳纤,这篇文章值得一看

光纤跳线作为光网络布线最基础的元件之一&#xff0c;被广泛应用于光纤链路的搭建中。 如今&#xff0c;光纤制造商根据应用场景的不同推出众多类型的光纤跳线&#xff0c;如 MPO / LC / SC / FC / ST 光纤跳线&#xff0c;单工/双工光纤跳线&#xff0c;单模/多模光纤跳线等&…

把maven本地库(windows)导入Nexus3(ubuntu)

1、在nexus中创建导入仓库 点“Create repository” 选择maven2(hosted) 填上对应的仓库name&#xff0c;Version policy选“Mixed” Hosted中的Deployment policy选择“Allow redeploy” 点“Create repository”创建仓库 创建好的仓库如下 记下仓库的url&#xff0c;下…

智慧教室课堂-专注度及考试作弊系统、课堂动态点名,情绪识别、表情识别和人脸识别结合

课堂专注度分析&#xff1a; 课堂专注度表情识别 作弊检测&#xff1a; 关键点计算方法 转头(probe)低头(peep)传递物品(passing) 侧面的传递物品识别 逻辑回归关键点 使用&#xff1a; 运行setup.py安装必要内容 python setup.py build develop 运行demo_inference.py 将…

ISO 27701-2019 隐私信息管理体系要求中文版 学习笔记

ISO 27701-2019: 隐私信息管理体系的新里程碑 随着数字化时代的到来&#xff0c;个人隐私保护变得愈发重要。组织和企业在处理个人数据时&#xff0c;如何确保隐私安全&#xff0c;成为了全球关注的话题。ISO 27701-2019标准&#xff0c;作为隐私信息管理体系&#xff08;PIMS&…

计算机的存储体系

计算机的存储分为内存和硬盘两大类。其中内存属于非持久化的存储设备&#xff0c;用于临时存储数据&#xff0c;设备掉电后数据会丢失&#xff1b;硬盘属于持久化的存储设备&#xff0c;设备掉电后数据不会丢失。 实际上在计算机领域存储的种类是非常多的&#xff0c;业界有时…

osgearth 3.5 vs 2019编译

下载源码 git clone --recurse-submodules https://github.com/gwaldron/osgearth.git 修改配置文件 主要是修改bootstrap_vcpkg.bat&#xff0c;一处是vs的版本&#xff0c;第二处是-DCMAKE_BUILD_TYPERELEASE 构建 执行bootstrap_vcpkg.bat vs中生成安装 vs2019打开bu…

用友电子凭证解决方案,加速企业电子凭证全链路管理

2023年&#xff0c;财政部等9部委联合推进电子凭证数据标准及试点工作&#xff0c;目前逐步扩大试点范围&#xff0c;覆盖市场应用高频的9类凭证。2024年&#xff0c;财政部办公厅发布了《关于继续开展电子凭证会计数据标准深化试点工作的通知》对电子凭证进行全流程常态化处理…

赛事|基于SprinBoot+vue的CSGO赛事管理系统(源码+数据库+文档)

CSGO赛事管理系统 目录 基于SprinBootvue的CSGO赛事管理系统 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3参赛战队功能模块 4合作方功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&…

人类行为验证处理方案 —— 脱离UI组件库实现登录、注册+表单校验

目录 01: 构建登录模块基础UI结构 02: 表单校验实现原理与方案分析 表单校验的实现原理 自定义表单校验方案分析 文章中的方案实现 03: 基于 vee-validate 实现普适的表单校验 04: 什么是人类行为验证&#xff1f;它的目的、实现原理、构建方案分别是什么&am…