Activity启动全过程解析

本文深入解析Android中的ActivityManagerService(AMS)机制,包括AMS的作用、初始化时机及其与ActivityThread、Instrumentation等组件间的交互方式。此外,还介绍了zygote进程、SystemServer进程等关键概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

一些问题
  1:zygote是什么?有什么作用?
  
  zygote意为“受精卵”。Android是基于Linux系统的,而在Linux中,所有的进程都是由init进程直接或者间接的fork出来的,zygote进程也不例外。在Android系统中,zygote是一个进程的名称,当你的手机开机的时候,Linux的内核加载完成之后就会启动一个“init”进程,在Linux系统中,所有的进程都是由”init”进程fork出来的,zygote进程也不例外。每一个App其实都是一个单独的dalvik虚拟机,既一个单独的进程。所以当系统里面的第一个zygote进程运行之后,在这之后再开启App,就相当于开启一个新的进程,而为了实现资源公用和更快的启动速度,Android系统开启新的进程的方式,是通过fork第一个zygote进程是实现的,so,除了第一个zygote进程,其他的进程都是zygote的子进程,这就是“受精卵”的意思了。
  
  2:SystemServer是什么?有什么作用?它和zygote有什么关系?
  
  首先要说的是,SystemServer也是一个进程,而且它是由zygote进程fork出来的。这个进程进程是Android Framework里面的两大重要进程之一 (另外一个就是zygote进程)。为什么说SystemServe重要呢?因为系统里面重要的服务都是在这个进程中开启的,比如ActivityManagerService、PackageMangerService、WindowMangerService等等。下面来看开启的代码:

public static void main(String argv[]) {
    //在加载首个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]);
                }
            }
         //开始fork SystemServer进程
     if (startSystemServer) {
                startSystemServer(abiList, socketName);
         }
}

接下来看看startSystemServer()做了些什么:

/**
 * Prepare the arguments and fork for the system server process.
 */
 private static boolean startSystemServer(String abiList, String socketName)
        throws MethodAndArgsCaller, RuntimeException {
        /* 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);

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

  3:ActivityManagerService是什么?有什么作用?什么时候初始化?
  
  在上面已经简单的解释了ActivityManagerService是什么,它初始化的时机也很明确,就是在SystemServer进程开启的时候,下面从代码中来看:
  

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() {
        //加载本地系统服务库,并进行初始化 
        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;
        }
    }

    /*
     * 初始化系统上下文对象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() {
        //初始化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);
    }
}

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

  4:上面我们提到了,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和zygote通过Socket进行IPC通信,通过前面我们知道,如果想要打开一个App,需要AMS去通知zygote进程,除此之外,其实所有Activity的开启、暂停、关闭都需要AMS来控制,所以说,AMS负责整个系统中所有Activity的生命周期。

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

  最后一个问题:Instrumentation是什么?有什么作用?它和ActivityThread又有什么关系?
  
  前面说过,每个Activity都会持有Instrumentation对象的一个引用,但是整个进程只会存在一个Instrumentation对象,当startActivityForResult()调用的时候,实际上还是调用了mInstrumentation.execStartActivity(),来看startActivityForResult()的实现:

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            ...ignore some code...    
        } else {
            if (options != null) {
                 //当现在的Activity有父Activity的时候会调用,但是在startActivityFromChild()内部实际还是调用的mInstrumentation.execStartActivity()
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }  
    }

由上面的方法,我们可以看出,确实调用了mInstrumentation.execStartActivity,再来看它的方法实现:

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
      try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }

所以当我们在程序中调用startActivity()的 时候,实际上调用的是Instrumentation的相关的方法。

Instrumentation意为“仪器”,我们先看一下这个类里面包含哪些方法。
这里写图片描述

我们可以看到,这个类里面大部分的方法都和Application、Activity有关,它其实就是用来完成Application和Activity的初始化以及生命周期管理的工具类,比如,我们来看callActivityOnCreate()方法:
这里写图片描述
对activity.performCreate(icicle);大家可能不熟悉,但是对于Activity的入口onCreate()我想一定是熟悉的,来看performCreate()的实现:

final void performCreate(Bundle icicle) {
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
}

如你看到的,onCreate()方法在这里调用。既然,Instrumentation如此的重要,为何我们在开发的过程黄总却从来没有见过它,那么这里就要说到ActivityThread了,他两什么关系,举个例子(不知道恰当否),ActivityThread是老板,Instrumentation就是老板娘,一个主外,一个主内。ActivityThread可能大家会陌生,但是我说主线程或者UI线程,我想大家就一定不会陌生了,没错,就是它。

AMS需要暂停一个Activity,先告诉ActivityThread,再由ActivityThread告诉Instrumentation,最后由Instrumentation去执行。

以上先介绍到这里,这篇文章我也是在网上看到,实验后稍加整理出来的,感谢那些大神。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值