一文读懂ActivityThread

ActivityThread是什么,是主线程吗?它是如何被创建的,以及它的作用又是什么呢?带着这些问题,我们一起来分析下ActivityThread。

全文分为以下几个部分,大家可根据需求阅读

ActivityThread是什么

ActivityThread是应用进程的初始化类,它的main()方法就是应用的入口方法,也就是说应用进程被创建后会调用ActivityThread.main()方法,关于这一点可以参考《Android App进程创建过程分析》中客户端发送创建进程和服务端响应创建进程内容。ActivityThread也是我们常说的主线程,但是这种描述不太准确,ActivityThread不是线程,只不过它是在运行在主线程(main)的main()方法中创建的对象,自然它也是运行在主线程中。只能说ActivityThread是主线程的一部分,但不并能代表主线程。我们从下面的profiler cpu usage图也能看出,ActivityThread.main()方法是在主线程(main)中调用的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N5zsEBak-1634819360670)(./thread_of_activity_thread.png)]

ActivityThread对象如何被创建的

 关于ActivityThread对象创建,分为两种情况:

  • system_server进程创建ActivityThread对象;
  • App进程创建ActivityThread对象;

system_server进程

 关于system_server进程(进程名为system_process)会创建ActivityThread对象,可能大家会有点疑惑,不过system_sever进程中确实存在ActivityThread对象的,这一点我们可以通过AS profiler工具验证。

在这里插入图片描述

既然知道system_server进程中存在ActivityThread对象,我们就来看下system_server进程中创建ActivityThread对象的过程。
在这里插入图片描述

从上面的时序图我们可以看到:在SystemServer.createSystemContext()方法中会调用ActivityThread静态方法systemMain(),得到ActivityThread对象,这个过程中也会创建Application对象,并调用其onCreate()方法。我们通过源码看下整个过程,首先看下SystemServer.createSystemContext()方法。

//frameworks\base\services\java\com\android\server\SystemServer.java
private void createSystemContext() {
    //得到ActivityThread对象,
    ActivityThread activityThread = ActivityThread.systemMain();
    //为mSystemContext变量赋值
    mSystemContext = activityThread.getSystemContext();
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

    final Context systemUiContext = activityThread.getSystemUiContext();
    systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}

该方法比较简单,首先通过ActivityThread静态方法systemMain()得到ActivityThread对象,接着给mSystemContext变量赋值,然后设置Context主题。我们重点看下ActivityThread.systemMain()方法。

//frameworks\base\core\java\android\app\ActivityThread.java
@UnsupportedAppUsage
public static ActivityThread systemMain() {
    if (!ActivityManager.isHighEndGfx()) {
        ThreadedRenderer.disable(true);
    } else {
        ThreadedRenderer.enableForegroundTrimming();
    }
    //创建ActivityThread对象
    ActivityThread thread = new ActivityThread();
    //然后调用attach方法,注意传入的两个参数;
    //第一个参数表示是system_server进程,第二个参数表示system_server进程是第一个被创建的应用类进程。
    thread.attach(true, 0);
    return thread;
}


/**
* @param system 用于标志是否是system_server进程调用的;
* @param startSeq 表示当前创建的是第几个app进程。
*/
private void attach(boolean system, long startSeq) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                UserHandle.myUserId());
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        final IActivityManager mgr = ActivityManager.getService();
        try {
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
   
        //.....省略部分代码......
    } else {
        //system_server创建ActivityThread对应else语句
        android.ddm.DdmHandleAppName.setAppName("system_process",
                UserHandle.myUserId());
        try {
            mInstrumentation = new Instrumentation();
            mInstrumentation.basicInit(this);
            ContextImpl context = ContextImpl.createAppContext(
                    this, getSystemContext().mPackageInfo);
            //创建Application对象,然后调用它的onCreate()方法
            mInitialApplication = context.mPackageInfo.makeApplication(true, null);
            mInitialApplication.onCreate();
        } catch (Exception e) {
            throw new RuntimeException(
                    "Unable to instantiate Application():" + e.toString(), e);
        }
    }
   //.....省略部分代码......
}

在systemMain()方法中会创建ActivityThread对象,然后调用attach(true, 0),true表示是system_server进程,0表示system_server是第一个被创建的应用进程。在attach()方法中会创建Application对象,并调用onCreate方法,Application具体创建过程和生命周期方法调用大家可以参考上面的时序图自己跟下代码。

App进程

 对于普通App进程中会创建ActivityThread对象这一点,想必大家不会有什么疑问。我们同样可以通过AndroidStudio profiler工具验证,比如下面所示的setting应用。

在这里插入图片描述

 和system_server进程不同,普通App进程中ActivityThread对象的创建是从ActivityThread.main()方法开始的,我们看下main()方法的具体实现。

public static void main(String[] args) {
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");

    AndroidOs.install();

    CloseGuard.setEnabled(false);
    //初始化Environment,调用该方法后;Environment类方法(比如getExternalStorageState())才能正确的起作用
    Environment.initForCurrentUser();

    // Make sure TrustedCertificateStore looks in the right place for CA certificates
    final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
    TrustedCertificateStore.setDefaultUserDirectory(configDir);

    Process.setArgV0("<pre-initialized>");
    //创建主线程Looper,主线程Looper是不可退出的。
    Looper.prepareMainLooper();

    // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
    // It will be in the format "seq=114"
    long startSeq = 0;
    if (args != null) {
        for (int i = args.length - 1; i >= 0; --i) {
            if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                startSeq = Long.parseLong(
                        args[i].substring(PROC_START_SEQ_IDENT.length()));
            }
        }
    }
    //创建ActivityThread对象,然后调用attach()方法。
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
    //将ActivityThread的Handler变量mH赋值给类变量sMainThreadHandler.
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }

    // End of event ActivityThreadMain.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    //进入loop循环,如果Looper中MessageQueue中没有消息,则会一阻塞。
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

main()方法主要做了以下几件事:

  • 初始化Environment;
  • 创建主线程Looper;
  • 创建ActivityThread对象,并调用其attach()方法;
  • 调用Looper.loop(),进入循环,阻塞式等待消息。

和systemMain()一样,main()方法也会调用attach()方法,只不过传入的参数不一样,main()方法中第一参数传入的为false,整个流程如下时序图所示:

在这里插入图片描述

从时序图中我们可以看出,attach()方法执行过程中会调用ActivityManagerService.attachApplicationLocked()方法,该方法执行过程可分为以下几个步骤:

  • 创建Application对象,并调用其onCreate()生命周期方法;
  • 判断是否需要启动Activity(对应通过start activity 的方式冷启动App);
  • 判断是否需要启动Service(对应通过start service 的方式冷启动App);
  • 判断是否有广播接收者需要接收广播(对应通过send broadcast 的方式冷启动App);

整个过程也很好解释了为什么冷启动一个App时会先调用Application的生命周期方法。我们简单看下ActivityManagerService.attachApplicationLocked()方法。

//ActivityManagerService.java
@GuardedBy("this")
private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid, int callingUid, long startSeq) {

    ProcessRecord app;
    long startTime = SystemClock.uptimeMillis();
    long bindApplicationTimeMillis;
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            app = mPidsSelfLocked.get(pid);
        }
        //省略部分代码......
    }

    
   //省略部分代码......

    try{
        //省略部分代码......
        checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
        bindApplicationTimeMillis = SystemClock.elapsedRealtime();
        mAtmInternal.preBindApplication(app.getWindowProcessController());
        final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
        if (app.isolatedEntryPoint != null) {
            //如果是isolate进程(可通过android:isolatedProcess设置),则不绑定Application
            thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
        } else if (instr2 != null) { //下面两种情况会调用ActivityThread.ApplicationThread.bindApplication()
            thread.bindApplication(processName, appInfo, providers,
                    instr2.mClass,
                    profilerInfo, instr2.mArguments,
                    instr2.mWatcher,
                    instr2.mUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.isPersistent(),
                    new Configuration(app.getWindowProcessController().getConfiguration()),
                    app.compat, getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, autofillOptions, contentCaptureOptions);
        } else {
            thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                    null, null, null, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.isPersistent(),
                    new Configuration(app.getWindowProcessController().getConfiguration()),
                    app.compat, getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, autofillOptions, contentCaptureOptions);
        }
        if (profilerInfo != null) {
            profilerInfo.closeFd();
            profilerInfo = null;
        }

        // Make app active after binding application or client may be running requests (e.g
        // starting activities) before it is ready.
        app.makeActive(thread, mProcessStats);
        checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
        mProcessList.updateLruProcessLocked(app, false, null);
        checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
        app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
    } catch (Exception e) {
        // todo: Yikes!  What should we do?  For now we will try to
        // start another process, but that could easily get us in
        // an infinite loop of restarting processes...
        Slog.wtf(TAG, "Exception thrown during bind of " + app, e);

        app.resetPackageList(mProcessStats);
        app.unlinkDeathRecipient();
        mProcessList.startProcessLocked(app, new HostingRecord("bind-fail", processName));
        return false;
    }

    // Remove this record from the list of starting applications.
    mPersistentStartingProcesses.remove(app);
    if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
            "Attach application locked removing on hold: " + app);
    mProcessesOnHold.remove(app);

    boolean badApp = false;
    boolean didSomething = false;

    // 判断是否需要启动Activity,当冷启动某个app的Activity的情况下,就会在此时启动Activity。
    if (normalMode) {
        try {
            didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }

    // 判断是否需要启动Service,当通过start service的方式冷启动一个app时,会在此时启动service
    if (!badApp) {
        try {
            didSomething |= mServices.attachApplicationLocked(app, processName);
            checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
            badApp = true;
        }
    }

    // 判断是否有广播接收者,情况和上面Activity、Service类似。
    if (!badApp && isPendingBroadcastProcessLocked(pid)) {
        try {
            didSomething |= sendPendingBroadcastsLocked(app);
            checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");
        } catch (Exception e) {
            // If the app died trying to launch the receiver we declare it 'bad'
            Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
            badApp = true;
        }
    }

    // Check whether the next backup agent is in this process...
    if (!badApp && backupTarget != null && backupTarget.app == app) {
        if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,
                "New app is backup target, launching agent for " + app);
        notifyPackageUse(backupTarget.appInfo.packageName,
                         PackageManager.NOTIFY_PACKAGE_USE_BACKUP);
        try {
            thread.scheduleCreateBackupAgent(backupTarget.appInfo,
                    compatibilityInfoForPackage(backupTarget.appInfo),
                    backupTarget.backupMode, backupTarget.userId);
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);
            badApp = true;
        }
    }

    if (badApp) {
        app.kill("error during init", true);
        handleAppDiedLocked(app, false, true);
        return false;
    }
    //省略部分代码......
    return true;
}

attachApplicationLocked()方法很长,我们只截取了其中的一部分;在这个方法中首先会调用ApplicationThread.bindApplication()方法,在该方法中通过主线程Handler对象H发送绑定Application的消息,在消息处理方法handleBindApplication创建Application对象,并调用其onCreate()生命周期方法。当然在handleBindApplication()方法中不仅仅是创建Application对象和调用其生命周期方法,还包括设置进程的名称、应用data数据存储路径、时间格式等。在之后的流程就是判断是否需要启动Activity、Service、处理广播。

 了解完ActivityThread对象是如何被创建的,我们在来看下它具体有哪些作用。

ActivityThread的作用

进程

  ActivityThread对于App进程来说,它是App的入口。此外ActivityThread还实现了创建主线程Looper、dump应用内存使用情况、获取应用包名等接口;具体内容这里不展开,大家可以自己去看看。我们看看ActivityThread对于四大组件的作用,一句话概括,ActivityThread管理着四大组件的生命周期方法的调用。

Activity

 在之前的《Android Activity启动过程分析》有提到Activity生命周期方法的具体调用过程,所以这里不在赘述。Activity的几个生命周期方法的调用过程如下:

onCreate: ActivityThread.handleLaunchActivity() -> ActivityThread.performLaunchActivity() -> Instrumentation.callActivityOnCreate() -> Activity.performCreate(icicle) -> Activity.onCreate()

onStart: ActivityThread.handleStartActivity() -> ActivityThread.performStart() -> Instrumentation.callActivityOnStart() -> Activity.onStart()

onResume: ActivityThread.handleResumeActivity() -> ActivityThread.performResumeActivity() -> Activity.performResume() -> Instrumentation.callActivityOnResume() -> Activity.onResume()

onPause: ActivityThread.handlePauseActivity() -> ActivityThread.performPauseActivity() -> ActivityThread.performPauseActivityIfNeeded() -> Instrumentation.callActivityOnPause() -> Activity.performPause() -> Activity.onPause()

onStop: ActivityThread.handleStopActivity() -> ActivityThread.performStopActivityInner() -> ActivityThread.callActivityOnStop() -> Activity.performStop() -> Activity.onStop()

onDestory: ActivityThread.handleDestroyActivity() -> ActivityThread.performDestroyActivity() -> Instrumentation.callActivityOnDestroy() -> Activity.performDestroy() -> Activity.onDestroy()

对于Service、BroadcastReceiver以及ContentProvider的生命周期方法调用具体细节,这里也不展开,下次再对她们一一单独讲解,这里只列举调用过程。

Service

onCreate: ActivityThread.scheduleCreateService() -> ActivityThread.handleCreateService() -> Service.onCreate()

onBind(): ActivityThread.scheduleBindService() -> ActivityThread.handleBindService() -> Service.onBind()

onStartCommand: ActivityThread.scheduleServiceArgs() -> ActivityThread.handleServiceArgs() -> Service.onStartCommand()

onDestroy: ActivityThread.scheduleStopService() -> ActivityThread.handleStopService() -> Service.onDestroy()

BroadcastReceiver

onReceive: ActivityThread.ApplicationThread.scheduleReceiver() -> ActivityThread.handleReceiver() -> Receiver.onReceive()

ContentProvider

onCreate: ActivityThread.ApplicationThread.scheduleInstallProvider() -> ActivityThread.handleInstallProvider() -> ActivityThread.installContentProviders() -> ActivityThread.installProvider() -> ContentProvider.attachInfo() -> ContentProvider.onCreate()

总结

 最后我们稍稍总结下

  • ActivityThread类是应用初始化类,它的main()方法是应用的入口方法;
  • ActivityThread不是线程,我们之所以称它为“主线程”,是因为它运行在主线程中;
  • ActivityThread负责创建Application对象以及管理其生命周期方法调用;
  • ActivityThread管理着四大组件的生命周期方法调用;

最后,留给大家一个作业——为什么四大组件的的生命周期方法是在主线程中被调用的?大家可以带着这个问题自己去研究下ActivityThread。另外,关于Activity的启动和App进程的创建可以参考以下的文章

Activity UI显示流程分析

Android Activity启动过程分析

Android App进程创建过程分析

  • 12
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值