浅谈Activity启动过程

浅谈Activity启动过程

本篇博客参考资料:
探索7.x源码, 全面解析Activity启动框架 (1)
《Android开发艺术探索》——任玉刚

在日常的开发中,我们通常使用startActivity(Intent intent)来启动一个新的Activity,我们能够如此简单的启动一个Activity要归功于Android开发团队完美的封装,屏蔽了Activity启动的底层细节,但是作为一个开发者,仅仅知道调用API是不够的,因此今天咱们就来好好聊聊一个Activity到底是怎么启动的。

首先从startActivity方法开始分析,startActivity有很多种重载方法,但是所有的重载方法最终都会调用startActivityForResult这个方法:

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        startActivityForResult(intent, -1);
    }
}

startActivityForResult的方法实现如下所示:

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
    @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
        mInstrumentation.execStartActivity(
            this, mMainThread.getApplicationThread(), mToken, this,
            intent, requestCode, options);
    .........
    .........
}

我省略了部分对于今天要学习的内容不重要的代码,在startActivityForResult方法中我们关注的是mParent==null这部分逻辑。可以看到,在startActivityForResult方法中调用了Instrumentation类下的execStartActivity方法,这个方法中我们需要关注一个参数——mMainThread.getApplicationThread(),这个参数的类型是ApplicationThread,而ApplicationThread是ActivityThread的内部类,ApplicationThread和ActivityThread在Activity的启动过程中起着重要的作用,这个之后会讲到。

接着看Instrumentation内部的execStartActivity方法:

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    // ...
    try {
        // ...
        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options); // 核心方法
        // ...
    } // ...
    return null;
}

可以看到,启动Activity是由ActivityManagerNative.getDefault()下的startActivity方法完成的。ActivityManagerService(AMS)是ActivityManagerNative的子类,而ActivityManagerNative继承自Binder并且实现了IActivityManager接口(也是一个Binder),所以ActivityManagerNative就是一个Binder,自然其子类AMS也是Binder,同时AMS也是IActivityManager接口的具体实现类。

ActivityManagerNative.getDefault()方法返回的是一个IActivityManager类型的Binder对象,其具体实现类正是AMS,同时AMS在ActivityManagerNative中是以单例模式对外提供的。

所以execActivity内部机制实际上就是调用了AMS的startActivity方法来启动Activity,于是我们接着进入AMS内部的startActivity,看看其实现机制:

@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
    Intent intent, String resolvedTyoe, IBinder resultTo, String 
    resultWho, int requestCode, int startFlags, 
    ProfilerInfo profilerInfo, Bundle options) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, options, UserHandle.getCallingUserId());
}

@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
    // ...
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, bOptions, false, userId, null, null);
}

可以看到,Activity的启动又经过startActivityAsUser方法交给了ActivityStackSupervisor的startActivityMayWait方法,startActivityMayWait又调用了startActivityLocked方法,startActivityLocked又调用了startActivityUncheckedLocked方法,startActivityUncheckedLocked又调用了ActivityStack的resumeTopActivitiesLocked方法,这个时候Activity的启动过程从ActivityStackSupervisor转移到了ActivityStack,而在resumeTopActivitiesLocked方法中又调用了resumeTopActivityInnerLocked方法,resumeTopActivityInnerLocked方法又调用了ActivityStackSupervisor的startSpecificActivityLocked方法,于是Activity的启动过程从ActivityStack又回到了ActivityStackSupervisor。
这里写图片描述

这么一大串的调用确实是让人头昏眼花,但我们不用担心,我们只需关注最后回到ActivityStackSupervisor的这个方法:

void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
    // 获取启动Activity的进程, 即Application
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);
    r.task.stack.setLaunchTime(r);

    if (app != null && app.thread != null) {
        try {
            // ...
            // 真正启动Activity的过程
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        }
        // ...
    }
    // ...
}

在startSpecificActivityLocked方法中,终于看到了真正启动Activity的方法realStartActivityLocked,在这个方法中我们关注这样一段代码:

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
        System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
        new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
        task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
        newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

app.thread的类型是IApplicationThread,而IApplicationThread是一个Binder类型的接口,这个接口中声明了大量的启动、停止Activity的方法,此外还包含了启动和停止Service的方法,因此IApplicationThread的实现者将拥有启动、停止Activity和Service的功能,而这个实现者就是ApplicationThread。

private class ApplicationThread extends ApplicationThreadNative

public abstract class ApplicationThreadNatibe extends Binder implements IApplicationThread

可以看到ApplicationThread继承自ApplicationThreadNative,而ApplicationThreadNatve继承自Binder同时实现了IApplicationThread接口。

于是在无数个方法和类中的传递后,Activity的启动过程最终来到了ApplicationThread中,如上面的代码所示,ApplicationThread通过scheduleLaunchActivity方法启动Activity:

public final void scheduleLaunchActivity(...) {
    ...

    ...

    sendMessage(H.LAUNCH_ACTIVITY, r);
}

scheduleLaunchActivity启动Activity的过程很简单,就是发送一个启动Activity的消息交给Handler处理,这个Handler被取名为H,让我们看一下在Handler H中是如何对这个消息进行处理的:

//这个类太长,我只帖出了我们用到的部分  
private class H extends Handler {  

    public void handleMessage(Message msg) {  
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));  
        switch (msg.what) {  
            //这里处理LAUNCH_ACTIVITY消息类型  
            case LAUNCH_ACTIVITY: {  
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");  
                ActivityClientRecord r = (ActivityClientRecord)msg.obj;  

                r.packageInfo = getPackageInfoNoCheck(  
                        r.activityInfo.applicationInfo, r.compatInfo);  
                //这里处理startActivity消息  
                handleLaunchActivity(r, null);  
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
            } break;  
            case RELAUNCH_ACTIVITY: {  
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");  
                ActivityClientRecord r = (ActivityClientRecord)msg.obj;  
                handleRelaunchActivity(r);  
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
            } break;  
            case PAUSE_ACTIVITY:  
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");  
                handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);  
                maybeSnapshot();  
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
                break;  
            ...  
        }  
}  

可以看到Handler H对”LAUNCH_ACTIVITY”消息的处理方式是调用ActivityThread下的handleLaunchActivity方法,handleLaunchActivity的源码如下:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {  
    ...

    if (localLOGV) Slog.v(  
        TAG, "Handling launch of " + r);  
    //performLaunchActivity真正完成了activity的调起,  
    //同时activity会被实例化,并且onCreate会被调用  
    Activity a = performLaunchActivity(r, customIntent);  

    if (a != null) {  
        r.createdConfig = new Configuration(mConfiguration);  
        Bundle oldState = r.state;  
        //目标activity的onResume会被调用  
        handleResumeActivity(r.token, false, r.isForward,  
                !r.activity.mFinished && !r.startsNotResumed);  

        ...
    }  
}  

终于发现performLaunchActivity方法最终完成了Activity的创建和启动,并且ActivityThread通过handleResumeActivity方法来调用Activity的onResume这一生命周期方法。

performLaunchActivity总结起来就是干了这几件事:

  1. 获取待启动的Activity的组件信息
  2. 创建Activity对象
  3. 尝试创建Application对象(若有则不再创建)
  4. 通过Activity的attach方法完成重要数据初始化
  5. 调用Activity的onCreate()生命周期方法

最后总结一下Activity的启动过程:当我们调用Activity类下的startActivity方法后,首先会调用startActivityForResult方法,这个方法内部接着会调用Instrumentation下的execStartActivity方法,execStartActivity内部是由AMS的startActivity方法实现的,从AMS的startActivity方法开始,Activity的启动过程就交给了ActivityStackSuperVisor,经过一系列反复调用,整个启动过程会分别交给ActivityStackSuperviosor和ActivityStack,最终又通过startSpecificActivityLocked方法重新交给ActivityStackSupervisor,startSpecificActivityLocked方法内部会调用readStartActivityLocked方法,这个方法就是真正开始启动Activity的方法。因为在这个方法中调用了ApplicationThread下的scheduleLaunchActivity方法,这个方法会发送一个启动Activity的消息给Handler H,Handler H会将Activity的启动交给ActivityThread下的handleLaunchActivity方法来实现,handleLaunchActivity方法的内部将Activity的启动交给了performLaunchActivity方法,Activity启动成功。

到此为止,整个Activity的启动过程算是告一段落了,需要注意的是,身为开发者我们不仅仅需要会调用api,还要对Android的内部机制进行一些‘适当’的了解,这个适当指的不是去深究Android的源码细节,而是要知道Android源码的大体流程,例如Activity的启动过程是怎样一个流程,会经过哪几个步骤,中间会有哪些重要的类参与这个过程,整个启动过程是怎样的一个思想。但是如果我们去研究这中间的每一行代码的话,不仅仅需要花费大量的时间,甚至还有可能得不偿失。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值