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

这篇具有很好参考价值的文章主要介绍了Android应用启动流程:从启动到可交互的过程解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

Android应用启动流程:从启动到可交互的过程解析,Android学习之路,android,面试,启动流程,java,优化

一、导读

我们继续总结学习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创建等过程

我们画个简单的图
Android应用启动流程:从启动到可交互的过程解析,Android学习之路,android,面试,启动流程,java,优化
Android应用启动流程:从启动到可交互的过程解析,Android学习之路,android,面试,启动流程,java,优化

下面贴一下代码:

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();
        
        创建ActivityThread
        ActivityThread 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传递过来的消息
    @Override
    public 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的onCreate
        
            mInstrumentation.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();

Android应用启动流程:从启动到可交互的过程解析,Android学习之路,android,面试,启动流程,java,优化

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

    真的开始启动 activity
    final 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.java
    public 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;
        

继续一系列调用
Android应用启动流程:从启动到可交互的过程解析,Android学习之路,android,面试,启动流程,java,优化

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


    /**
     * Extended implementation of activity launch. Used when server requests a launch or relaunch.
     */
    @Override
    public 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) {
        }
        
        window
            
        theme
        
        //当实例化Activity对象后,继续执行callActivityOnCreate
        if (r.isPersistable()) {
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } else {
            mInstrumentation.callActivityOnCreate(activity, r.state);
        }
    }

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

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

三、 推荐阅读

Java 专栏

SQL 专栏

数据结构与算法

Android学习专栏文章来源地址https://www.toymoban.com/news/detail-672323.html

到了这里,关于Android应用启动流程:从启动到可交互的过程解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • android源码学习- APP启动流程(android12源码)

    百度一搜能找到很多讲APP启动流程的,但是往往要么就是太老旧(还是基于android6去分析的),要么就是不全(往往只讲了整个流程的一小部分)。所以我结合网上现有的文章,以及源码的阅读和调试,耗费了3整天的时间,力求写出一篇最完整,最详细,最通俗易懂的文章,

    2024年02月11日
    浏览(44)
  • Android framework学习指南之Launcher启动过程原理分析

    Launcher是一个用来显示系统中已经安装的应用程序的应用程序,Launcher 在启动过程中会请求PackageManagerService 返回系统中已经安装的应用程序的信息,并将这些信息封装成一个快捷图标列表显示在系统屏幕上,这样用户可以通过点击这些快捷图标来启动相应的应用程序,它的作

    2024年02月03日
    浏览(47)
  • C/C++源程序到可执行程序exe的全过程(及汇编和反汇编的区别)

    1.C/C++源程序到可执行程序exe的全过程(及汇编和反汇编的区别) 一个现代编译器的主要工作流程如下: 源程序(source code)→预处理器(preprocessor)→编译器(compiler)→汇编程序(assembler)→目标程序(object code)→连接器(链接器,Linker)→可执行程序(executables)。 简

    2024年02月10日
    浏览(39)
  • CS 144 Lab Four 收尾 -- 网络交互全流程解析

    对应课程视频: 【计算机网络】 斯坦福大学CS144课程 本节作为Lab Four的收尾,主要带领各位来看看网络交互的整体流程是怎样的。 这里以tcp_ipv4.cc文件为起点,来探究一下cs144是如何实现整个协议栈的。 首先,项目根路径中的 tun.sh 会使用 ip tuntap 技术创建虚拟 Tun/Tap 网络设备

    2024年02月04日
    浏览(41)
  • 实战-数据从数据库到前端 javaweb数据交互流程解析

    目录 git地址 用到的技术及组件 一、创建maven项目  二、导入相关依赖      三、设置数据库及对象 1、数据库建表 2、创建实体类User 3、编写mybatis配置文件 mybatis-config.xml 放入资源文件夹 4、配置Mapper代理 5、Mapper自动映射 四、新建service层自动执行查询         1、首先将

    2024年01月17日
    浏览(41)
  • 韩版传奇 2 源码分析与 Unity 重制(二)客户端启动与交互流程

    该专题将会分析 LOMCN 基于韩版传奇 2,使用 .NET 重写的传奇源码(服务端 + 客户端),分析数据交互、状态管理和客户端渲染等技术,此外笔者还会分享将客户端部分移植到 Unity 和服务端用现代编程语言重写的全过程。 在这一篇文章中,我们将从客户端入手,分析从 TCP 连接

    2024年02月03日
    浏览(65)
  • 人机交互学习-4 交互设计过程

    标识用户需要并建立需求 开发满足需求的候选设计方案 构建设计的交互版本 评估设计 以用户为中心 稳定的可用性标准 迭代 用户:直接与产品交互,以期望完成某个任务的人。 用户分类:主要用户、二级用户、三级用户。 主要用户:经常使用系统的用户 二级用户:偶尔使

    2024年02月09日
    浏览(46)
  • springboot启动流程源码解析(带流程图)

    本文自己写的(头条也有这篇文章),若有问题,请指正。 大致流程如下: 1. 初始化SpringApplication,从META-INF下的spring.factories读取 ApplicationListener/ApplicationContextInitializer 2.运行SpringApplication的run方法 3.读取项目中环境变量、jvm配置信息、配置文件信息等 4.创建Spring容器对象(

    2024年02月08日
    浏览(41)
  • Android系统启动(四) — Launcher 启动过程

    1 Launcher 概述 系统启动的最后一步是启动一个应用程序来显示系统中已经安装的应用程序,这个应用程序就叫做 Launcher 。 Launcher 在启动过程中会请求 PackageManagerService 返回系统中已经安装的应用程序信息,并将这些信息封装成一个快捷图标列表显示在系统屏幕上,这样用户就

    2024年02月01日
    浏览(40)
  • Android启动过程 - Zygote

    在上一篇中,我们知道zygote进程是在`/system/etc/init/hw/init.rc`文件中配置,由init进程启动的。看下init中关于zygote的配置: 其中第一句import /system/etc/init/hw/init.${ro.zygote}.rc中的ro.zygote为属性,从源码看,对应的文件: core/rootdir/init.zygote64.rc、core/rootdir/init.zygote32.rc和init.zygote64_

    2024年02月22日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包