你必须掌握的Activity启动过程

前言:众所周知,Activity是四大组件之首,网上关于Activity的博客也有很多,相信大家对于他的生命周期和启动模式有了相应的了解。本文就不再对这些进行讲述了,我要从源码的角度对一个Activity的启动过程进行分析。

我们知道,当startActivity被调用的时候,可以启动一个Activity,但是你知道这个Activity是如何被启动的吗?你知道这个Activity是啥时候被创建的吗?为什么onCreate是Activity的执行入口呢?所有的这一切都被系统封装好了,对我们来说是透明的,我们使用的时候仅仅是传递一个intent然后startActivity就可以达到目的了,不用担心,阅读了本文以后,你将会了解它的背后到底做了哪些事情。在分析之前,我先介绍几个类:

Activity:startActivity方法的真正实现在Activity中
Instrumentation:用来辅助Activity完成启动Activity的过程
ActivityThread(包含ApplicationThread + ApplicationThreadNative + IApplicationThread):真正启动Activity的实现都在这里

开始源码分析:Activity#startActivity()

public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        // Note we want to go through this call for compatibility with
        // applications that may have overridden the method.
        startActivityForResult(intent, -1);
    }
}

public void startActivityForResult(Intent intent, int requestCode) {
    startActivityForResult(intent, requestCode, null);
}

从上面的代码中我们发现:调用startActivty实际上最后还是调用了startActivityForResult 方法。那么,我们沿着这个方法继续深入探讨:
Activity#startActivityForResult

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
    if (mParent == null) {
      //真正执行启动activity的代码逻辑
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        //启动activity返回的结果处理
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
     
             mStartedActivity = true;
        }

        cancelInputsAndStartExitTransition(options);
        // TODO Consider clearing/flushing other event sources and events for child windows.
    } else {
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            // Note we want to go through this method for compatibility with
            // existing applications that may have overridden it.
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

从上面代码我们发现,实际上调用的启动activity方法的还是Instrumentation类。也就是我们第二个要研究的重点类。
Instrumentation#execStartActivity

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
   //这个whoThread执行了启动activity
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
          //遍历一遍,查询是否存在这个activity,activity类存放在intent中。
            for (int i = 0; i < N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        //这里通过ActivityManager启动了activity
        int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
        //检查启动activity返回的结果
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

从上面,相关代码我都加上了注释。有两点:
1:真正执行activity的启动过程的是ActivityManagerNative.getDefault().startActivity。
2:执行启动activity之后,有一个代码检查结果。
我们先看看第2个方法:
Instrumentation#checkStartActivityResult

public static void checkStartActivityResult(int res, Object intent) {
    if (res >= ActivityManager.START_SUCCESS) {
        return;
    }

    switch (res) {
        case ActivityManager.START_INTENT_NOT_RESOLVED:
        case ActivityManager.START_CLASS_NOT_FOUND:
            if (intent instanceof Intent && ((Intent) intent).getComponent() != null)
                throw new ActivityNotFoundException(
                        "Unable to find explicit activity class "
                                + ((Intent) intent).getComponent().toShortString()
                                + "; have you declared this activity in your AndroidManifest.xml?");
            throw new ActivityNotFoundException(
                    "No Activity found to handle " + intent);
        case ActivityManager.START_PERMISSION_DENIED:
            throw new SecurityException("Not allowed to start activity "
                    + intent);
        case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
            throw new AndroidRuntimeException(
                    "FORWARD_RESULT_FLAG used while also requesting a result");
        case ActivityManager.START_NOT_ACTIVITY:
            throw new IllegalArgumentException(
                    "PendingIntent is not an activity");
        case ActivityManager.START_NOT_VOICE_COMPATIBLE:
            throw new SecurityException(
                    "Starting under voice control not allowed for: " + intent);
        case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY:
            // Fail silently for this case so we don't break current apps.
            // TODO(b/22929608): Instead of failing silently or throwing an exception,
            // we should properly position the activity in the stack (i.e. behind all current
            // user activity/task) and not change the positioning of stacks.
            Log.e(TAG,
                    "Not allowed to start background user activity that shouldn't be displayed"
                            + " for all users. Failing silently...");
            break;
        default:
            throw new AndroidRuntimeException("Unknown error code "
                    + res + " when starting " + intent);
    }
}

有没有一些熟悉的异常信息呢?比如:如果我们没有在xml配置文件中注册activity,那么启动activity的时候是不是会报Unable to find explicit activity class......。

那么,我们回到第1个问题,真正执行的启动代码在
ActivityManagerNative.getDefault().startActivity()中:
我们发现:ActivityManagerNative是抽象类,getDefault() 方法返回的是IActivityManager,也仅仅是一个接口而已;那么实际上我们跟踪代码会发现startActivity()也仅仅是IActivityManager的一个方法而已,那么我们是不是到这里就束手无策了呢?
答案当然是否定的。
1:我们找到IApplicationThread的接口截图:

你必须掌握的Activity启动过程_第1张图片
IApplicationThread.png

我们可以发现很多类似activity生命周期的方法,onCreate,onStart,onResume等等。是不是明白了什么呢?是的,activity的生命周期实际上是在调用这些方法,但是这只是一个接口,我们需要继续找到他的实现类。别急,下面会讲到;

2:我们需要找到IActivityManager的实现类。
那么,我们来看看IActivityManager#startActivity()方法:ActivityManagerNative抽象类,这个抽象类使用了代理

  class ActivityManagerProxy implements IActivityManager;
//这个代理类实现了IActivityManager的startActivity方法,我们看看:
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
        String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(caller != null ? caller.asBinder() : null);
    data.writeString(callingPackage);
    intent.writeToParcel(data, 0);
    data.writeString(resolvedType);
    data.writeStrongBinder(resultTo);
    data.writeString(resultWho);
    data.writeInt(requestCode);
    data.writeInt(startFlags);
    if (profilerInfo != null) {
        data.writeInt(1);
        profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
    } else {
        data.writeInt(0);
    }
    if (options != null) {
        data.writeInt(1);
        options.writeToParcel(data, 0);
    } else {
        data.writeInt(0);
    }
  //上面都是一些数据的填写,这里是智行事务的逻辑代码
    mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
    reply.readException();
    int result = reply.readInt();
    reply.recycle();
    data.recycle();
    return result;
}
private IBinder mRemote;

我们从代码发现了mRemote是一个IBinder,调用了IBinder的transact()方法,真是IBinder无处不在啊。这说明了启动Activity实际上也是进行了进程间的通信。是不是又明白了什么?比如A应用要启动B应用的某个Activity,怎么做?进程间通信帮你解决。伟大的IBinder,如果你们需要的话,后期我会出一个IBinder机制讲解,可以通过源码分析,因为我个人认为,结合源码分析会更加有说服力并使得自己记忆更加牢固。(有这样需求的请留言让我看到哦...)

那么mRemote的初始化问题大家应该都清楚吧,上面我们调用了ActivityManagerNative.getDefault(),代码我就不贴出来了,使用了单利模式,大家可以进去看看。

我们从上面知道了IApplicationThread执行了启动activity,那么谁实现了该接口呢?当然是ApplicationThread,这个类是ActivityThread的内部类。里面很多的方法都对应了相关的activity生命周期方法,我们仅仅来看看scheduleLaunchActivity:

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
            int procState, Bundle state, PersistableBundle persistentState,
            List pendingResults, List pendingNewIntents,
            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

        updateProcessState(procState, false);

        ActivityClientRecord r = new ActivityClientRecord();

        r.token = token;
        r.ident = ident;
        r.intent = intent;
        r.referrer = referrer;
        r.voiceInteractor = voiceInteractor;
        r.activityInfo = info;
        r.compatInfo = compatInfo;
        r.state = state;
        r.persistentState = persistentState;

        r.pendingResults = pendingResults;
        r.pendingIntents = pendingNewIntents;

        r.startsNotResumed = notResumed;
        r.isForward = isForward;

        r.profilerInfo = profilerInfo;

        r.overrideConfig = overrideConfig;
        updatePendingConfiguration(curConfig);

        sendMessage(H.LAUNCH_ACTIVITY, r);
    }

我们看到最后的sendMessage,往下走我们找到H类的处理消息方法

public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                r.packageInfo = getPackageInfoNoCheck(
                        r.activityInfo.applicationInfo, r.compatInfo);
                handleLaunchActivity(r, null);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break; ....

代码没有全部贴出,仅仅是看看LAUNCH_ACTIVITY 的处理即可。我们可以看到handleLaunchActivity(),沿着这个方法继续往下寻找,最后发现performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ActivityInfo aInfo = r.activityInfo;
    ComponentName component = r.intent.getComponent();
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to instantiate activity " + component
                + ": " + e.toString(), e);
        }
    }
        ......
    return activity;
}

最后的逻辑都在这里,通过我们的intent数据,结合classLoader找到了相关的类并且加载进来了。详细的逻辑在这里就不讲太多了。

其实我们了解看源代码并不需要了解各种细节,只是需要了解他的框架即可。如果你深入了解了细节,恐怕会发生钻牛角尖的情况。这样对于整体的把握可能会不好。当然,如果你是做ROM开发或者个人已经掌握了Android源码框架,深入研究未尝不可。

你可能感兴趣的:(你必须掌握的Activity启动过程)