【凯子哥带你学Framework】Activity启动过程全解析

It’s right time to learn Android’s Framework !

前言

  • 一个App是怎么启动起来的?
  • App的程序入口到底是哪里?
  • Launcher到底是什么神奇的东西?
  • 听说还有个AMS的东西,它是做什么的?
  • Binder是什么?他是如何进行IPC通信的?
  • Activity生命周期到底是什么时候调用的?被谁调用的?
  • 等等…

你是不是还有很多类似的疑问一直没有解决?没关系,这篇文章将结合源码以及大量的优秀文章,站在巨人的肩膀上,更加通俗的来试着解释一些问题。但是毕竟源码繁多、经验有限,文中不免会出现一些纰漏甚至是错误,还恳请大家指出,互相学习。

学习目标

  1. 了解从手机开机第一个zygote进程创建,到点击桌面上的图标,进入一个App的完整流程,并且从源码的角度了解到一个Activity的生命周期是怎么回事
  2. 了解到ActivityManagerServices(即AMS)、ActivityStack、ActivityThread、Instrumentation等Android framework中非常重要的基础类的作用,及相互间的关系
  3. 了解AMS与ActivityThread之间利用Binder进行IPC通信的过程,了解AMS和ActivityThread在控制Activity生命周期起到的作用和相互之间的配合
  4. 了解与Activity相关的framework层的其他琐碎问题

写作方式

这篇文章我决定采用一问一答的方式进行。

其实在这之前,我试过把每个流程的代码调用过程,用粘贴源代码的方式写在文章里,但是写完一部分之后,发现由于代码量太大,整篇文章和老太太的裹脚布一样——又臭又长,虽然每个重要的操作可以显示出详细调用过程,但是太关注于细节反而导致从整体上不能很好的把握。所以在原来的基础之上进行了修改,对关键的几个步骤进行重点介绍,力求语言简洁,重点突出,从而让大家在更高的层次上对framework层有个认识,然后结合后面我给出的参考资料,大家就可以更加快速,更加高效的了解这一块的整体架构。

主要对象功能介绍

我们下面的文章将围绕着这几个类进行介绍。可能你第一次看的时候,印象不深,不过没关系,当你跟随者我读完这篇文章的时候,我会在最后再次列出这些对象的功能,相信那时候你会对这些类更加的熟悉和深刻。

  • ActivityManagerServices,简称AMS,服务端对象,负责系统中所有Activity的生命周期
  • ActivityThread,App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作
  • ApplicationThread,用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯。
  • ApplicationThreadProxy,是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是通过该代理与ActivityThread进行通信的。
  • Instrumentation,每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作。
  • ActivityStack,Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。
  • ActivityRecord,ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像。
  • TaskRecord,AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。如果你清楚Activity的4种launchMode,那么对这个概念应该不陌生。

主要流程介绍

下面将按照App启动过程的先后顺序,一问一答,来解释一些事情。

让我们开始吧!

zygote是什么?有什么作用?

首先,你觉得这个单词眼熟不?当你的程序Crash的时候,打印的红色log下面通常带有这一个单词。

zygote意为“受精卵“。Android是基于Linux系统的,而在Linux中,所有的进程都是由init进程直接或者是间接fork出来的,zygote进程也不例外。

在Android系统里面,zygote是一个进程的名字。Android是基于Linux System的,当你的手机开机的时候,Linux的内核加载完成之后就会启动一个叫“init“的进程。在Linux System里面,所有的进程都是由init进程fork出来的,我们的zygote进程也不例外。

我们都知道,每一个App其实都是

  • 一个单独的dalvik虚拟机
  • 一个单独的进程

所以当系统里面的第一个zygote进程运行之后,在这之后再开启App,就相当于开启一个新的进程。而为了实现资源共用和更快的启动速度,Android系统开启新进程的方式,是通过fork第一个zygote进程实现的。所以说,除了第一个zygote进程,其他应用所在的进程都是zygote的子进程,这下你明白为什么这个进程叫“受精卵”了吧?因为就像是一个受精卵一样,它能快速的分裂,并且产生遗传物质一样的细胞!

SystemServer是什么?有什么作用?它与zygote的关系是什么?

首先我要告诉你的是,SystemServer也是一个进程,而且是由zygote进程fork出来的。

知道了SystemServer的本质,我们对它就不算太陌生了,这个进程是Android Framework里面两大非常重要的进程之一——另外一个进程就是上面的zygote进程。

为什么说SystemServer非常重要呢?因为系统里面重要的服务都是在这个进程里面开启的,比如
ActivityManagerService、PackageManagerService、WindowManagerService等等,看着是不是都挺眼熟的?

那么这些系统服务是怎么开启起来的呢?

在zygote开启的时候,会调用ZygoteInit.main()进行初始化

public static void main(String argv[]) {

     ...ignore some code...

    //在加载首个zygote的时候,会传入初始化参数,使得startSystemServer = true
     boolean startSystemServer = false;
     for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            ...ignore some code...

         //开始fork我们的SystemServer进程
     if (startSystemServer) {
                startSystemServer(abiList, socketName);
         }

     ...ignore some code...

}

我们看下startSystemServer()做了些什么

    /**留着这个注释,就是为了说明SystemServer确实是被fork出来的
     * Prepare the arguments and fork for the system server process.
     */
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {

         ...ignore some code...

        //留着这段注释,就是为了说明上面ZygoteInit.main(String argv[])里面的argv就是通过这种方式传递进来的
        /* Hardcoded command line to start the system server */
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--runtime-init",
            "--nice-name=system_server",
            "com.android.server.SystemServer",
        };

        int pid;
        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

        //确实是fuck出来的吧,我没骗你吧~不对,是fork出来的 -_-|||
            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

ActivityManagerService是什么?什么时候初始化的?有什么作用?

ActivityManagerService,简称AMS,服务端对象,负责系统中所有Activity的生命周期。

ActivityManagerService进行初始化的时机很明确,就是在SystemServer进程开启的时候,就会初始化ActivityManagerService。从下面的代码中可以看到

public final class SystemServer {

    //zygote的主入口
    public static void main(String[] args) {
        new SystemServer().run();
    }

    public SystemServer() {
        // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode();
    }

    private void run() {

        ...ignore some code...

        //加载本地系统服务库,并进行初始化 
        System.loadLibrary("android_servers");
        nativeInit();

        // 创建系统上下文
        createSystemContext();

        //初始化SystemServiceManager对象,下面的系统服务开启都需要调用SystemServiceManager.startService(Class<T>),这个方法通过反射来启动对应的服务
        mSystemServiceManager = new SystemServiceManager(mSystemContext);

        //开启服务
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }

        ...ignore some code...

    }

    //初始化系统上下文对象mSystemContext,并设置默认的主题,mSystemContext实际上是一个ContextImpl对象。调用ActivityThread.systemMain()的时候,会调用ActivityThread.attach(true),而在attach()里面,则创建了Application对象,并调用了Application.onCreate()。
    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
    }

    //在这里开启了几个核心的服务,因为这些服务之间相互依赖,所以都放在了这个方法里面。
    private void startBootstrapServices() {

        ...ignore some code...

        //初始化ActivityManagerService
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);

        //初始化PowerManagerService,因为其他服务需要依赖这个Service,因此需要尽快的初始化
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

        // 现在电源管理已经开启,ActivityManagerService负责电源管理功能
        mActivityManagerService.initPowerManagement();

        // 初始化DisplayManagerService
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

    //初始化PackageManagerService
    mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
       mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

    ...ignore some code...

    }

}

经过上面这些步骤,我们的ActivityManagerService对象已经创建好了,并且完成了成员变量初始化。而且在这之前,调用createSystemContext()创建系统上下文的时候,也已经完成了mSystemContext和ActivityThread的创建。注意,这是系统进程开启时的流程,在这之后,会开启系统的Launcher程序,完成系统界面的加载与显示。

你是否会好奇,我为什么说AMS是服务端对象?下面我给你介绍下Android系统里面的服务器和客户端的概念。

其实服务器客户端的概念不仅仅存在于Web开发中,在Android的框架设计中,使用的也是这一种模式。服务器端指的就是所有App共用的系统服务,比如我们这里提到的ActivityManagerService,和前面提到的PackageManagerService、WindowManagerService等等,这些基础的系统服务是被所有的App公用的,当某个App想实现某个操作的时候,要告诉这些系统服务,比如你想打开一个App,那么我们知道了包名和MainActivity类名之后就可以打开

Intent intent = new Intent(Intent.ACTION_MAIN);  
intent.addCategory(Intent.CATEGORY_LAUNCHER);              
ComponentName cn = new ComponentName(packageName, className);              
intent.setComponent(cn);  
startActivity(intent); 

但是,我们的App通过调用startActivity()并不能直接打开另外一个App,这个方法会通过一系列的调用,最后还是告诉AMS说:“我要打开这个App,我知道他的住址和名字,你帮我打开吧!”所以是AMS来通知zygote进程来fork一个新进程,来开启我们的目标App的。这就像是浏览器想要打开一个超链接一样,浏览器把网页地址发送给服务器,然后还是服务器把需要的资源文件发送给客户端的。

知道了Android Framework的客户端服务器架构之后,我们还需要了解一件事情,那就是我们的App和AMS(SystemServer进程)还有zygote进程分属于三个独立的进程,他们之间如何通信呢?

App与AMS通过Binder进行IPC通信,AMS(SystemServer进程)与zygote通过Socket进行IPC通信。

那么AMS有什么用呢?在前面我们知道了,如果想打开一个App的话,需要AMS去通知zygote进程,除此之外,其实所有的Activity的开启、暂停、关闭都需要AMS来控制,所以我们说,AMS负责系统中所有Activity的生命周期。

在Android系统中,任何一个Activity的启动都是由AMS和应用程序进程(主要是ActivityThread)相互配合来完成的。AMS服务统一调度系统中所有进程的Activity启动,而每个Activity的启动过程则由其所属的进程具体来完成。

这样说你可能还是觉得比较抽象,没关系,下面有一部分是专门来介绍AMS与ActivityThread如何一起合作控制Activity的生命周期的。

Launcher是什么?什么时候启动的?

当我们点击手机桌面上的图标的时候,App就由Launcher开始启动了。但是,你有没有思考过Launcher到底是一个什么东西?

Launcher本质上也是一个应用程序,和我们的App一样,也是继承自Activity

packages/apps/Launcher2/src/com/android/launcher2/Launcher.java

public final class Launcher extends Activity
        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
                   View.OnTouchListener {
   
                   }

Launcher实现了点击、长按等回调接口,来接收用户的输入。既然是普通的App,那么我们的开发经验在这里就仍然适用,比如,我们点击图标的时候,是怎么开启的应用呢?如果让你,你怎么做这个功能呢?捕捉图标点击事件,然后startActivity()发送对应的Intent请求呗!是的,Launcher也是这么做的,就是这么easy!

那么到底是处理的哪个对象的点击事件呢?既然Launcher是App,并且有界面,那么肯定有布局文件呀,是的,我找到了布局文件launcher.xml

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
    android:id="@+id/launcher">

    <com.android.launcher2.DragLayer
        android:id="@+id/drag_layer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <!-- Keep these behind the workspace so that they are not visible when
             we go into AllApps -->
        <include
            android:id="@+id/dock_divider"
            layout="@layout/workspace_divider"
            android:layout_marginBottom="@dimen/button_bar_height"
            
Android框架中,Activity是一种用户界面的组件,用于展示用户界面和处理用户交互。ActivityAndroid应用程序的核心组件之一。它负责管理用户界面的生命周期和交互。当应用程序启动时,会创建一个或多个Activity,并且在用户与应用程序进行交互时,Activity会根据用户的操作进行相应的响应。 在Android框架中,创建一个Activity需要创建一个Activity的子类,并在子类中实现Activity在生命周期的各种状态之间转变时系统调用的回调方法。通常,在Android Studio中创建一个Activity的方式有两种: 第一种方式是通过右击包名,选择New -> Activity -> Empty Activity。在弹出的界面中输入Activity和布局的名称,系统会自动为我们创建布局,并在AndroidManifest.xml文件中自动注册当前Activity。 第二种方式是通过右击包名,选择New -> Java Class,输入Activity的名称。然后,在AndroidManifest文件中手动注册Activity,将Activity的名称添加到application标签中。 无论使用哪种方式创建Activity,都需要在Activity的子类中重写onCreate()方法,并在该方法中引用布局文件,以便使用该布局。 总结起来,ActivityAndroid框架中的一个核心组件,用于展示用户界面和处理用户交互。创建Activity需要创建Activity的子类,并在子类中实现Activity在生命周期的各种状态之间转变时系统调用的回调方法。在Android Studio中,可以通过两种方式创建Activity,并在创建的Activity中引用布局文件。
评论 63
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值