Android应用启动流程:从启动到可交互的过程解析

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。
专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。

目录

  • 一、导读
    • 1.1 启动知识储备
    • 1.2 Zygote进程
    • 1.3 SystemServer进程
    • 1.4 AMS(Activity Manager Service)
    • 1.5 APP进程(ActivityThread)
  • 二、启动流程概览
    • 2.1 用户点击桌面图标
    • 2.2 创建app进程
    • 2.3 创建 application
    • 2.4 activity启动显示
  • 三、 推荐阅读

在这里插入图片描述

一、导读

我们继续总结学习Android 基础知识,温故知新。

还是在多年前做系统应用开发的时候,通过编译源码学习了一遍APP的启动过程,
最近在整理应用启动优化相关的文档,打算重新梳理一遍,并整理成一个通俗易懂的文档,以备后面查看。
在学习过程中,大家最好是把源码下载下来。

1.1 启动知识储备

启动过程比较复杂,涉及到的知识点非常多,建议通过其他文章进行学习。

1.2 Zygote进程

Zygote进程是Android设备启动时由init进程创建和启动,之后不断接收来自应用程序的请求。
Zygote进程预先创建一个虚拟机和一些共享资源,以提高应用程序的启动速度和系统资源的利用效率。
同时,Zygote进程也负责处理应用程序进程的环境初始化和加载核心类库等操作。
每当有新的应用程序启动请求到达时,Zygote进程会fork出一个子进程(应用程序进程)来运行该应用程序。

1.3 SystemServer进程

SystemServer进程是Android操作系统的一个关键进程,它在设备启动时由init进程创建的。

SystemServer进程是一个守护进程,在系统运行期间一直存在,负责启动和管理各个核心系统服务,如AMS、Window Manager、Package Manager等。

1.4 AMS(Activity Manager Service)

AMS(Activity Manager Service)是SystemServer进程中的一个关键组件,负责管理所有应用程序的生命周期和交互。它监控应用程序的启动、暂停、恢复和销毁,
并协调应用程序之间的切换和交互。除此之外,AMS还处理任务栈管理、权限管理、用户通知等相关任务。

1.5 APP进程(ActivityThread)

APP进程是指在Android系统中运行的应用程序进程。每个运行的应用程序都会分配一个或多个独立的APP进程来承载应用的执行环境。
每个APP进程都是Zygote进程通过fork系统调用创建的子进程。

ActivityThread 是Android应用程序的主线程,负责管理和调度应用程序中的所有Activity的生命周期以及处理一些系统事件。

ActivityThread的主要职责包括:

  1. 创建和启动应用程序的主Activity。
  2. 处理应用程序的消息循环,接收和分发来自系统和应用程序的消息。
  3. 管理应用程序的所有Activity的生命周期,包括创建、启动、暂停、恢复、停止和销毁等。
  4. 处理应用程序的资源加载和更新,包括布局文件、图片、字符串等资源的加载。
  5. 处理应用程序的窗口管理,包括窗口的创建、显示、隐藏和更新等操作。
  6. 与AMS (Activity Manager Service)通信,处理Activity的启动、停止、切换等请求,并接收来自AMS的指令和请求。
  7. 处理应用程序的异常错误,包括崩溃、ANR (Application Not Responding)等情况的处理。

二、启动流程概览

涉及到多个进程之间的通信:
1、用户点击图标后,Laucher(手机桌面)会通过binder的方式通知SystemServer进程。
2、SystemServer收到信息,内部的AMS(Activity Manager Service)通知Zygote去创建APP进程,通过反射调用ActivityThread.main方法,即创建主线程。
3、APP进程创建后(Zygote进行fork),通过回调通知AMS。
4、AMS收到信息后经过一些列调用,通知APP进程(ActivityThread)创建Application
5、Application 之后,继续执行调用到ClientLifecycleManager,进行Activity创建等过程

我们画个简单的图
图片
在这里插入图片描述

下面贴一下代码:

2.1 用户点击桌面图标

Launcher获取到AMS的binder,之后进入到SystemServer进程。

然后调用的zygote进程,fork出一个新的app进程。

2.2 创建app进程

ActivityThread


应用进程启动的入口函数main()方法中,会调用Looper相关的初始化和循环方法,从而让主线程的Looper进入循环状态,保证app进程的一直运行状态public static void main(String[] args) {. ..//looper绑定主线程Looper.prepareMainLooper();创建ActivityThreadActivityThread thread = new ActivityThread();thread.attach(false, startSeq);//looper开启无限循环读取消息Looper.loop();. ..}private void attach(boolean system, long startSeq) {if (!system) {. ..final IActivityManager mgr = ActivityManager.getService();try {// 通知 AMS, 并将当前进程的binder句柄传给AMS绑定管理起来mgr.attachApplication(mAppThread, startSeq);} catch (RemoteException ex) {}. ..}. ..}

attachApplication 这个流程会分两步:
1、创建应用的application对象
2、activity启动显示

2.3 创建 application

IActivityManager.aidl

void attachApplication(in IApplicationThread app, long startSeq);

ActivityManagerService


// 这里接受APP传递过来的消息@Overridepublic final void attachApplication(IApplicationThread thread, long startSeq) {synchronized (this) {// 通过 Binder 获取 PID ,PID和UID都是进程创建应用的时候系统指定的int callingPid = Binder.getCallingPid();final int callingUid = Binder.getCallingUid();final long origId = Binder.clearCallingIdentity();attachApplicationLocked(thread, callingPid, callingUid, startSeq);}}@GuardedBy("this")private final boolean attachApplicationLocked(IApplicationThread thread,int pid, int callingUid, long startSeq) {// *** 1、通知APP进程进行初始化操作,初始化application,创建应用进程的application对象if (app.isolatedEntryPoint != null) {} else if (app.instr != null) {thread.bindApplication(processName, appInfo, providers, ...);} else {thread.bindApplication(processName, appInfo, providers, ...);}// *** 2、 通知APP拉起指定的MainActivity,调用ATMS的启动页面的方法,后面继续介绍// See if the top visible activity is waiting to run in this process...if (normalMode) {try {if (mStackSupervisor.attachApplicationLocked(app)) {didSomething = true;}} catch (Exception e) {}}}

IApplicationThread.aidl


void bindApplication(in String packageName, in ApplicationInfo info, ...);

我们来看看 Application 是如何创建的
ActivityThread

AMS调用过来,具体看上面的代码
public final void bindApplication(String processName, ApplicationInfo appInfo, ...) {sendMessage(H.BIND_APPLICATION, data);
}public void handleMessage(Message msg) {switch (msg.what) {case BIND_APPLICATION:AppBindData data = (AppBindData)msg.obj;handleBindApplication(data);break;. ..}
}private void handleBindApplication(AppBindData data) {Application app;try{classLoader加载APK中的dex,并且加载APK的资源final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,appContext.getClassLoader(), false, true, false);final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);通过 calssLoader 来创建 application 对象app=data.info.makeApplication(data.restrictedBackupMode,null);try{调用Application的onCreatemInstrumentation.onCreate(data.instrumentationArgs);}catch(Exception e){}try{mInstrumentation.callApplicationOnCreate(app);}catch(Exception e){}} ... 
}public Application newApplication(ClassLoader cl, String className, Context context) 。。{Application app = getFactory(context.getPackageName()).instantiateApplication(cl, className);app.attach(context);return app;
}(Application) cl.loadClass(className).newInstance();

在这里插入图片描述

2.4 activity启动显示

接着上面的代码 mStackSupervisor.attachApplicationLocked(app);

ActivityStackSupervisor
方法realStartActivityLocked();

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {final String processName = app.processName;boolean didSomething = false;Activity启动的入口try {if (realStartActivityLocked(activity, app, top == activity, true)) {}} catch (RemoteException e) {}return didSomething;}真的开始启动 activityfinal boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,boolean andResume, boolean checkConfig) throws RemoteException {// Create activity launch transaction.final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,r.appToken);clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,// TODO: Have this take the merged configuration instead of separate global// and override configs.mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,r.persistentState, results, newIntents, mService.isNextTransitionForward(),profilerInfo));// Schedule transaction.mService.getLifecycleManager().scheduleTransaction(clientTransaction);}

ActivityManagerService

ClientLifecycleManager getLifecycleManager() {return mLifecycleManager;}

ClientLifecycleManager

    通过代码,我们可以看到,获取的client就是 ActivityThreadIApplicationThread是一个AIDL文件void scheduleTransaction(ClientTransaction transaction) throws RemoteException {final IApplicationThread client = transaction.getClient();transaction.schedule();}

ClientTransaction

        /** Target client. */private IApplicationThread mClient;public void schedule() throws RemoteException {mClient.scheduleTransaction(this);}

ClientTransactionHandler

//ActivityThread中没有复写scheduleTransaction,会执行到父类的方法//public final class ActivityThread extends ClientTransactionHandler//ClientTransactionHandler.javapublic abstract class ClientTransactionHandler {void scheduleTransaction(ClientTransaction transaction) {transaction.preExecute(this);//发送消息sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);}}

ActivityThread.java

case EXECUTE_TRANSACTION:final ClientTransaction transaction = (ClientTransaction) msg.obj;mTransactionExecutor.execute(transaction);break;

继续一系列调用
在这里插入图片描述

最后调用到ActivityThread,创建并启动Activity,由于篇幅原因,Activity资源加载相关的内容我们在另一篇文章介绍。

/*** Extended implementation of activity launch. Used when server requests a launch or relaunch.*/@Overridepublic Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {final Activity a = performLaunchActivity(r, customIntent);return a;}Activity实例化过程/**  Core implementation of activity launch. */private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {Activity activity = null;try {// 通过反射实例化Activity对象java.lang.ClassLoader cl = appContext.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);} catch (Exception e) {}windowtheme//当实例化Activity对象后,继续执行callActivityOnCreateif (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}}

接下来就是执行 Activity 生命周期函数

所用的源码不同,代码可能会有些许差别。

三、 推荐阅读

Java 专栏

SQL 专栏

数据结构与算法

Android学习专栏

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

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

相关文章

淘宝API技术解析,实现按图搜索淘宝商品

淘宝提供了开放平台接口(API)来实现按图搜索淘宝商品的功能。您可以通过以下步骤来实现: 1. 获取开放平台的访问权限:首先,您需要在淘宝开放平台创建一个应用,获取访问淘宝API的权限。具体的申请步骤和要求…

【分析绘图】R语言实现一些常见的绘图

微生信-在线绘图网站 线性图 library(ggplot2)x <- rnorm(100, 14, 5) # rnorm(n, mean 0, sd 1) y <- x rnorm(100, 0, 1) ggplot(data NULL, aes(x x, y y)) # 开始绘图geom_point(color "darkred") # 添加点annotate("text",x 13,…

JSON简介及前端简单解析(一)

JSON现在常用来做前后端数据交互&#xff0c;两个蝴蝶飞只是简单的对JSON做一下讲解和简单使用。关于JSON,我还了解的远远不够。由于本人经验有限&#xff0c;嘴皮子不溜&#xff0c;所以学术性&#xff0c;概念性&#xff0c;底层性的知识点暂时不做介绍。文章中有错误之处&am…

Android6:片段和导航

创建项目Secret Message strings.xml <resources><string name"app_name">Secret Message</string><string name"welcome_text">Welcome to the Secret Message app!Use this app to encrypt a secret message.Click on the Star…

飞天使-k8s基础组件分析-持久化存储

文章目录 emptyDirhostpathpv和pvc介绍nfs作为静态pv案例nfs作为动态pv案例使用本地文件夹作为pv改变默认存储类及回收策略参考文档 emptyDir 重启文件还有&#xff0c;但是如果杀了进程&#xff0c;则会丢失文件 创建pod # kubectl apply –f redis.yaml校验pod是否处于运行&…

基于CentOS搭建私有仓库harbor

环境&#xff1a; 操作系统&#xff1a;CentOS Linux 7 (Core) 内核&#xff1a; Linux 3.10.0-1160.el7.x86_64 目录 安装搭建harbor &#xff08;1&#xff09;安装docker编排工具docker compose &#xff08;2&#xff09;下载Harbor 安装包 &#xff08;3&…

mysql使用flashback恢复数据

常在河边走&#xff0c;哪有不湿鞋。如果我们经常操作数据库&#xff0c;很有可能就会造成误操作&#xff0c;假如我们不幸误删了数据&#xff0c;有没有办法快速恢复呢&#xff1f; 这里&#xff0c;我们就以用的最多的mysql举例&#xff0c;聊聊如何快速恢复数据。mysql官方貌…

vue2 vue中的常用指令

一、为什么要学习Vue 1.前端必备技能 2.岗位多&#xff0c;绝大互联网公司都在使用Vue 3.提高开发效率 4.高薪必备技能&#xff08;Vue2Vue3&#xff09; 二、什么是Vue 概念&#xff1a;Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套 **构建用户界面 ** 的 渐进式 …

nginx服务

一、nginx概述&#xff1a; 1.Nginx简介&#xff1a; Nginx是一个高性能的HTTP和反向代理服务器。是一款轻量级的高性能的web服务器/反向代理服务器/电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器&#xff0c;单台物理服务器可支持30 000&#xff5e;50 000个并发请求…

回归预测 | MATLAB实现WOA-BP鲸鱼优化算法优化BP神经网络多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现WOA-BP鲸鱼优化算法优化BP神经网络多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现WOA-BP鲸鱼优化算法优化BP神经网络多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基本…

IDEA远程开发

IDEA远程开发 前期准备 IDEA的远程开发是在本地去操昨远程服务器上的代码&#xff0c;所以我们先需要准备一台服务器,在此我使用vmware虚拟出ubuntu-20.04.6的Server版本,以便后面演示。 Ubuntu的Java环境配置 JDK8 sudo apt install openjdk-8-jdkmaven sudo apt instal…

无涯教程-PHP - preg_replace()函数

preg_replace() - 语法 mixed preg_replace (mixed pattern, mixed replacement, mixed string [, int limit [, int &$count]] ); preg_replace()函数的操作与POSIX函数ereg_replace()相同&#xff0c;不同之处在于可以在模式和替换输入参数中使用正则表达式。 可选的输…