一篇文章搞定《APP的启动流程》

一篇文章搞定《APP的启动流程》

  • 前言
  • 冷启动、温启动、热启动
  • 启动中的重要成员简介
    • zygote进程
    • Instrumentation
    • SystemServer进程
    • ActivityManagerService
    • Binder
    • ActivityThread
  • 启动的步骤详解
    • 一、点击桌面图标
    • 二、创建进程
    • 三、初始化APP进程
    • 四、APP进程与System_server的绑定
    • 五、初始化Applacation And Activity
  • 启动优化(浅谈)
    • 透明主题优化
    • 设置闪屏图片主题
    • Application 优化
    • 闪屏页业务优化
    • 利用Hook
  • 总结

前言

前面已经铺垫了Binder、Handler、View的绘制流程
那么该来看看APP的启动流程了,是如何启动了我们这些重要的组件
本文会按照步骤和启动需要的成员并附带一点点源码进行讲解。
以了解熟悉启动的流程为主。不会大篇幅的利用源码深入。
本文结构:
1、冷启动、温启动、热启动
2、启动中的重要成员简介
3、启动的步骤详解
4、启动优化(浅谈)

冷启动、温启动、热启动

  • 冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,然后再根据启动的参数,启动对应的进程组件,这个启动方式就是冷启动。
  • 温启动:当启动应用时,后台已有该应用的进程,但是Activity可能因为内存不足被回收。这样系统会从已有的进程中来启动这个Activity,这个启动方式叫温启动。
  • 热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动对应的进程组件,这个方式叫热启动。

由于冷启动相对于其他启动方式多了进程的创建(Zygote进程fork创建进程)以及应用的资源加载和初始化(Application的创建及初始化),所以相对来说会比较耗时,所以我们一般说的App启动优化一般指的都是App的冷启动优化。
启动中的重要

启动中的重要成员简介

zygote进程

不说的冠冕堂皇的,就简单的给大家总结两条:

  • zygote进程是由Linux中的init进程,fock出来的进程。
  • 在Android中,所有的应用的进程都是由zygote进程fork出来的,一个新的App进程就是zygote进程的子进程。

Zygote进程首先会fork自己孵化出的SystemServer进程,它的main函数主要负责:

  • 启动binder线程池,这是SystemServer与其他进程通信的基础
  • 初始化Looper
  • 创建了SystemServiceManager对象,它会启动Android中的各种服务。包括AMS、PMS、WMS
  • 启动桌面进程,这样才能让用户见到手机的界面。
  • 开启loop循环,开启消息循环,SystemServer进程一直运行,保障其他应用程序的正常运行。

注意:init进程在开启的时候就创建了,所以在开机的时候我们的zygote进程和ServiceManager都被创建出来了。

Instrumentation

工具类,它用来监控应用程序和系统的交互,包装了 ActivityManagerService 的调用,一些插件化方案就是通过 hook 该类实现的。

SystemServer进程

SystemServer是由zygote进程fork出来的第一个进程,SystemServer和Zygote是Android Framework最重要的2个进程。 系统里面重要的服务都是在这个进程里面开启的,比如ActivityManagerService、PackageManagerService、WindowManagerService。
应用启动流程基本是围绕着ActivityManagerService和ActivityThread展开。

ActivityManagerService

  • 在Android系统中,任何一个Activity的启动都是由AMS和App进程(主要是ActivityThread)相互配合来完成的。
  • 他在SystemServer创建后被初始化
  • App进程与AMS通过Binder机制进行跨进程通信
  • AMS(SystemServer进程)与zygote通过Socket进行跨进程通信。

Binder

Binder就不细说了,Android系统中的IPC跨进程通信。
就是《一篇文章搞定〈Binder〉》中的内容

ActivityThread

ActivityThread 是 Android 系统中驱动应用程序的主线程,它的作用是管理应用程序的生命周期和交互。ActivityThread 负责启动应用程序的入口 Activity,提供与 Android 系统之间的通信桥梁,同时也处理了应用程序的消息队列和事件循环。
在 App 启动过程中,ActivityThread 主要负责以下几个重要的工作:

  • 创建一个主线程 Looper ,用于处理消息队列和事件循环。
  • 加载应用程序的主题、资源和布局文件。
  • 通过调用 Instrumentation 的 callApplicationOnCreate() 方法触发应用程序的生命周期,初始化应用程序,并创建首个 Activity。

启动的步骤详解

图中的红色线条为Binder通信
紫色线条是Socket通信

一、点击桌面图标

  • Launcher 捕获点击事件,调用 Activity#startActivity();
  • 点击图标发生在Launcher应用的进程,startActivity()函数最终是由Instrumentation通过Android的Binder跨进程通信机制 发送消息给 system_server 进程;
    在这里插入图片描述

二、创建进程

在 system_server 中,启动进程的操作会先调用ActivityManagerService#startProcessLocked() 方法,该方法内部调用 Process.start(android.app.ActivityThread);而后通过 socket 通信告知 Zygote 进程 fork 子进程,即 app 进程。
在这里插入图片描述

三、初始化APP进程

  • 开启主线程 app 进程启动后,首先是实例化 ActivityThread,并执行其main()函数
  • main()函数中创建 ApplicationThread,Looper,Handler 对象,并开启主线程消息循环Looper.loop()。
  • 调用 ActivityThread#attach(false)方法进行 Binder 通信

源码如下:ActivityThread.java

public static void main(String[] args) {
···
     Looper.prepareMainLooper();

     ActivityThread thread = new ActivityThread();
     thread.attach(false);

     if (sMainThreadHandler == null) {
         sMainThreadHandler = thread.getHandler();
     }
 ···
     Looper.loop();
 ···
 }


 private void attach(boolean system) {
 ···
     if (!system) {
     ···
         final IActivityManager mgr = ActivityManager.getService();
         try {
             mgr.attachApplication(mAppThread);
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }
     ···
     } else {
    ···
     }
 ···
 }

在这里插入图片描述

四、APP进程与System_server的绑定

  • 调用 ActivityThread#attach(false)方法进行 Binder 通信(在方法里进行下一步)
  • 通知system_server进程执行 ActivityManagerService#attachApplication(mAppThread)方法
  • system_server进程在收到请求后,进行一系列准备工作后(创建该App进程信息表)再通过binder IPC向App进程发送scheduleLaunchActivity请求;
  • 这相当于是APP进程发信息给system_server进程,进行一个绑定的过程。创建通信的过程。
    在这里插入图片描述

五、初始化Applacation And Activity

  • App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程(ActivityThread)发送LAUNCH_ACTIVITY消息;
  • 主线程(ActivityThread)在收到Message后,通过HandleLaunchActivity创建目标Activity,并回调Activity.onCreate()等方法。
  • 到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面
    在这里插入图片描述
    到此为止App的启动流程就结束了,上图也是完整的启动流程模型图。

启动优化(浅谈)

透明主题优化

为了解决启动窗口白屏问题,使用透明主题来解决这个问题,但是治标不治本。

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowIsTranslucent">true</item>
</style>

设置闪屏图片主题

这个挺多APP还在用的哦
为了更顺滑无缝衔接我们的闪屏页,可以在启动 Activity 的 Theme中设置闪屏页图片,这样启动窗口的图片就会是闪屏页图片,而不是白屏。

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowBackground">@mipmap/launch_image</item>   //闪屏页图片  
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowContentOverlay">@null</item>
</style>

这样设置的话,就会在冷启动的时候,展示闪屏页的图片,等App进程初始化加载入口 Activity (也是闪屏页) 就可以无缝衔接。
其实这种方式并没有真正的加速应用进程的启动速度,而只是通过用户视觉效果带来的优化体验。

Application 优化

通过上面的流程,我们可以知道。会先初始化我们的Application,所以在Application中初始化减少耗时操作能有效的帮我提升。
通常,有机会优化这些工作以实现性能改进,这些常见问题包括:

  • 复杂繁琐的布局初始化
  • 阻塞主线程 UI 绘制的操作,如 I/O 读写或者是网络访问.
  • Bitmap 大图片或者 VectorDrawable加载
  • 其它占用主线程的操作

有很多第三方组件(包括App应用本身)都在 Application 中抢占先机,完成初始化操作。
比如Bugly,x5内核初始化,SP的读写,友盟等组件。那就放到子线程中去初始化。

闪屏页业务优化

例如埋点,点击流,数据库初始化等这类必须在主线程初始化的动作。那么我们可以放在闪屏页。
一般:闪屏页政展示总时间 = 组件初始化时间 + 剩余展示时间。
也就是2000ms的总时间,组件初始化了800ms,那么就再展示1200ms即可。

通过上面的流程分析,我们可以知道 Application 初始化后会调用 attachBaseContext() 方法,再调用 Application 的 onCreate(),再到入口 Activity的创建和执行 onCreate() 方法。所以我们就可以在 Application 中记录启动时间。
Application.java

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    SPUtil.putLong("application\_attach\_time",
        System.currentTimeMillis());//记录Application初始化时间  
}

有了启动时间,我们得知道入口的 Acitivty 显示给用户的时间(View绘制完毕)
那就是入口Activity的onWindowFocusChanged喽
入口Activity.java

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    long appAttachTime = SPUtil.getLong("application\_attach\_time");
    long diffTime = System.currentTimeMillis() - appAttachTime;
    //从application到入口Acitity的时间  
    
    //所以闪屏页展示的时间为 2000ms - diffTime.  
}

利用Hook

  • ActivityManagerService

在Android系统中,启动应用的过程通常是通过ActivityManagerService来进行管理的。可以通过Hook ActivityManagerService的方式,在应用启动时进行一些优化操作。例如,可以在应用启动前创建一个空的Activity,并在其onCreate方法中执行一些耗时操作,如初始化数据或预加载资源。然后,通过Hook ActivityManagerService,将启动的Activity替换为这个空的Activity形式,这样就可以减少应用启动的耗时。

  • AMS和PMS

Android系统在应用启动的过程中,会对Activity、Service等组件的启动进行权限验证和安全检查。这个过程较为耗时,可以通过Hook ActivityManagerService(AMS)和PackageManagerService(PMS)来绕过这些检查,从而提升启动速度。例如,可以通过Hook AMS和PMS,修改应用的启动流程,跳过权限验证和安全检查的过程,从而减少启动耗时。

总结

APP的启动流程学问是很大的。需要对Android的源码进行一定的理解。
但是我们在开发中需要有意识的注意会影响APP启动的操作。
毕竟APP的启动是第一扇门。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【软件架构】企业架构4A定义

文章目录 前言战略、BA、DA、AA、TA五者的关系1、业务架构&#xff08;BA&#xff09;2、数据架构&#xff08;DA&#xff09;3、应用架构&#xff08;AA&#xff09;4、技术架构&#xff08;TA&#xff09;总结 前言 业务架构是跨系统的业务架构蓝图&#xff0c;应用架构、数…

【Nodejs】nodejs内置模块(中)

1.路劲处理模块 path 1.1 模块概览 在nodejs中&#xff0c;path是个使用频率很高&#xff0c;但却让人又爱又恨的模块。部分因为文档说的不够清晰&#xff0c;部分因为接口的平台差异性。将path的接口按照用途归类&#xff0c;仔细琢磨琢磨&#xff0c;也就没那么费解了。 1.…

Python基于PyTorch实现卷积神经网络分类模型(CNN分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 卷积神经网络&#xff0c;简称为卷积网络&#xff0c;与普通神经网络的区别是它的卷积层内的神经元只覆…

FUNBOX_1靶场详解

FUNBOX_1靶场复盘 这个系列的靶场给出的干扰因素都挺多的&#xff0c;必须从中找到有用的线索才可以。 这个靶场你扫描到ip地址后打开网页会发现&#xff0c;ip自动转换成域名了&#xff0c;所以我们需要添加一条hosts解析才可以。 192.168.102.190 funbox.fritz.box从目录…

vue中预览静态pdf文件

方法 // pdf预览 viewFileCompare() { const pdfUrl "/static/wjbd.pdf"; window.open(pdfUrl); }, // 下载 downloadFile(){ var a document.createElement("a"); a.href "/static/wjbd.pdf"; a.…

自学网络安全(黑客),遇到问题怎么解决

自学网络安全很容易学着学着就迷茫了&#xff0c;找到源头问题&#xff0c;解决它就可以了&#xff0c;所以首先咱们聊聊&#xff0c;学习网络安全方向通常会有哪些问题&#xff0c;看到后面有惊喜哦 1、打基础时间太长 学基础花费很长时间&#xff0c;光语言都有几门&#xf…

专项练习-1数据结构-02字符串

1. 下面关于「串」的叙述中&#xff0c;哪一个是不正确的&#xff1f;&#xff08; &#xff09; A 串是字符的有限序列 B 空串是由空格构成的串 C 模式匹配是串的一种重要运算 D 串既可以采用顺序存储&#xff0c;也可以采用链式存储 正确答案&#xff1a;B 官方解析&…

如何在3ds max中创建可用于真人场景的巨型机器人:第 1部分

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 创建主体 步骤 1 打开 3ds Max。 打开 3ds Max 步骤 2 在左侧视口中&#xff0c;按键盘上的 Alt-B 键。它 打开视口配置窗口。 打开“锁定缩放/平移”和“匹配位图”选项。单击“文件”并转到参考 …

实验二十四、滞回比较器电压传输特性的测量

一、题目 滞回比较器电压传输特性的测量。 二、仿真电路 电路如图1所示。 为便于观察电压传输特性的变化&#xff0c;输入信号采用信号发生器产生的幅值为 10 V 10\,\textrm V 10V、频率为 20 Hz 20\,\textrm{Hz} 20Hz 的三角波电压。采用虚拟的运算放大电路&#xff0c;其…

从娱乐产品到效率工具,ARknovv首款AR眼镜回归“AR本质”

如果说2022年是AR的元年&#xff0c;2023年则有望成为消费级AR眼镜的新拐点。 今年AR眼镜行业发展明显加快&#xff0c;且不断有大厂入局&#xff1a;今年2月小米发布无线AR眼镜探索版&#xff1b;3月荣耀也推出了一款全新的观影眼镜&#xff1b;而苹果在6月发布的MR头显Visio…

[面试官,你坐好],今天我给你吹下卡顿监控

这是一篇面试总结稿&#xff0c;根据之前的面试过程以一种模拟面试的风格进行阐述。 面试官: 自我介绍下 诶&#xff1f;这面试官头发还比较多&#xff0c;应该不牛逼&#xff0c;心里踏实了不少。我: 面试官你好&#xff0c;我叫**&#xff0c;5年工作经验。曾经跟OPPO产品PK&…

甄云质量管理解决方案——插上数字“羽翼”,实现PPAP落地

导语 质量管理是供应链管理中非常重要的一环&#xff0c;通过制定和开展质量相关的活动&#xff0c;确保产品符合质量标准和一致性要求。质量管理水平的高低直接影响供应链的整体效率和最终效益&#xff0c;关乎企业形象和品牌声誉&#xff0c;已然是企业的生命线。 作为采购…

ES6:Object.assign方法详解

ES6&#xff1a;Object.assign方法详解 1、前言2、语法3、基本用法3.1 目标对象和源对象无重名属性3.2 目标对象和源对象有重名属性3.3 有多个源对象3.4 其他情况3.4.1 只有一个参数时&#xff0c;Object.assign会直接返回该参数3.4.2 如果该参数不是对象&#xff0c;则会先转成…

el-table 表头设置渐变色

<el-table :data"tableData" stripe><el-table-column prop"name" label"测试" align"left"></el-table-column><el-table-column prop"code" label"测试1" align"left"></…

科技云报道:边缘云赛道开启,谁能成为首个“出线”厂商?

科技云报道原创。 每一轮底层技术变革&#xff0c;都会带来全新的商业机遇。随着万物智联时代到来&#xff0c;大量数据产生的源头由传统的中心化向分散数据源变革&#xff0c;越来越多云边协同场景的出现&#xff0c;使得边缘云成为计算领域数据处理的新范式之一。 自2020年…

OR-Tools工具安装(Python-Vs code)-自用

安装&#xff08;已安装python以及Vs code&#xff09; pip安装 python -m pip install --user ortools安装完成示意如下&#xff1a; 验证安装 python -c "import ortools; print(ortools.__version__)"输出结果为版本号

网络:TCP/IP协议

1. OSI七层参考模型 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 2. TCP/IP模型 应用层 传输层 网络层 数据链路层 物理层 3. 各链路层对应的名称 应用层对应的是协议数据单元 传输层对应的是数据段 网络层对应的是数据包 链路层对应的是数据帧 物理层对应的是比特…

Mysql 简介

Mysql 简介 学习目的 MySQL作为目前最流行的关系型数据库管理系统之一&#xff0c;因其开源免费的特性&#xff0c;成为小型Web应用的重点关注对象。几乎所有的动态Web应用基本都在使用MySQL作为数据管理系统。学习MySQL的目的也是为了更好地理解数据库相关的SQL注入漏洞&…

uniapp实战

上面是tab栏&#xff0c;下面是swiper&#xff0c;&#xff0c;tab和swiper和 红色滑块 动态变化&#xff0c;&#xff0c; 遇到的问题&#xff1a; 往下滚动 tab栏 吸顶&#xff1a; position:sticky; z-index:99; top:0;swiper切换触发 change 事件&#xff0c; :current …

【Unity2D】相机移动以及设置相机边界

添加相机 添加相机时&#xff0c;首先需要在unity中添加 Cinemachine 包 第一次使用这个包时&#xff0c;需要在Package Manager中搜索并安装 安装Camera Mechine包后&#xff0c;添加2D Camera 设置跟随对象为Ruby &#xff08;从Hierarchy中将Ruby拖动到Follow中&#xff0…
最新文章