中道崩阻——Activity启动源码学习记录

Activity的启动流程学习记录

学习章节为:《Android开发艺术探索》第9章+《Android源码设计模式解析与实战》第5、15章

前言

看了刚哥的艺术探索和源码设计模式感觉一脸懵逼,于是尝试着自己看源码,发现更加懵逼了。。。先不说逻辑,就是里面的各种属性、对象、方法之类的都看的眼花缭乱,甚至有点反胃。。。不过俗话说的好书读百遍其义自见,在不断的尝试和思考后,终于算是有了一点点懂了。所以记下来,作为记录,也作为后续深入的基础。

一般来说,我们程序员通常喜欢把很复查的操作一层一层封装起来,使得最后暴露出来的接口很简单,让使用者无脑使用而不需要关注底层的实现。而Android系统做的也是这种事儿。我们使用一个Activity只需要建立、注册、调用onCreate()开始操作即可,而底层的东西Android工程师们都帮我们写好了。而写好的那部分,也是一层一层的封装。我们读源码的时候就是需要逆序而行,把这一层一层的封装给拆开来。当然过程肯定也是从外向内, 从表层到底层的。

底层的东西以我的水平看不大清楚,所以本文所述记录还是会非常多的停留在表层。静待后续探索。(如果想看还行的,直接跳到最后,看最后一个链接就行了。

开始~

主要涉及的类有ActivityActivityThread 及其内部类 ApplicationThreadActivityManagerServiceActivityStackSupervisor等。其实里头还有好多类,但是跟 Activity 启动相关的,先关注这几个类。

  1. 首先让我们回想一下我们启动一个Activity是如何启动的:
    就是通过使用
    startActivity(new Intent(MainActivity.this,xxxActivity.class))

来启动一个Activity。而这个方法最后会调用 startActivityForResult() 方法,如下:

    //Activity.java中
    public void startActivityForResult(@RequiresPermission 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());
            }
            ...
    }

上面的 mInstrumentation.execStartActivity() 如下:

    //Instrumentation.java中
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;

        ...
        /**
          *上面execStartActity()中传入的参数需要所以说。
          *Context 输入了 this
          *IBinder 传入了 mMainThread.getApplicationThread() ____这个ApplicationThread不得了,很重要。
          Intent 传入了咱们的 new Intent(MainActivity.this,xxxActivity.class)
          */
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);

            int result = ActivityManager.getService()  这儿,看这里
                .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) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

要注意代码中说的传入参数哦,很重要。然后看 ActivityManager.getService().startActivity() 这个方法,我的 AOSP 中直接使用 ctrl + B 是看不到 startActivity() 这个方法的,所以只有先看一下 getService() 是个何方神圣:

    //ActivityManager.java中
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton IActivityManagerSingleton =
            new Singleton() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);这儿,熟不熟悉哈哈
                    return am;
                }
            };

所以其实,是个Binder()机制的用法。在 AIDL 的用法中我们直到服务端是会有一个类来实现 .Stub 然后做具体的事情了。根据两本书的介绍,这个类就是大名鼎鼎的 ActivityManagerService 。所以这里记住了所有调用 ActivityManager.getService().xxxx 的操作都可以直接到 AMS 中找实现方法。所以我们直接到 AMS 中找 startActivity()方法如下:

    //ActivityManagerService.java中
    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, ...) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                ...);
    }

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, ... ,int startFlags, ...) {   这里还有个startFlags,熟不熟悉~2333
        enforceNotIsolatedCaller("startActivity");
        ...
        敲黑板,下面的方法,我的 AOSP 中是 mActivityStarter. 而 刚哥书上的是 mStackSupervisor
        //不过我在AMS的构造方法中发现了这个:
        //mActivityStarter = new ActivityStarter(this, mStackSupervisor);
        //所以其实ActivityStarter可能还是调用了ActivityStackSupervisor。
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
    }

上面方法的传入参数我省略了很多,在这里可以看到之前说的很重要的 ApplicationThreadIntent 一起全程跟了下来。然后就进入。。。卧槽,太复杂了(其实是我没找到那条调用链))。。。我们就直接说最后的结果吧

最后经过 ActivityStackSupervisor -> ActivityStack -> ActivityStackSupervisor 
我们最终找到了如下代码:
//ActivityStackSupervisor.java 中
    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);
        ...
        if (app != null && app.thread != null) {
            try {
                ...
                realStartActivityLocked(r, app, andResume, checkConfig); 这儿,看这里
                return;
            } catch (RemoteException e) {
                ...
            }
            ...
        }
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

----------------------下面是realStartActivityLocked----------------------

省略了N多代码。
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
                ...
                app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                        System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, !andResume,
                        mService.isNextTransitionForward(), profilerInfo);
                ...
        return true;
    }

这个 app.thread 很重要。还记得之前在代码中说的

IBinder 传入了 mMainThread.getApplicationThread() ____这个ApplicationThread不得了,很重要。

么,app.thread就是这样玩意儿。那这玩意儿又是啥呢?

//ActivityThread.java 中
final ApplicationThread mAppThread = new ApplicationThread();

//ActivityThread内部类 ApplicationThread
private class ApplicationThread extends IApplicationThread.Stub {
        ...
        看到 .Stub很熟悉吧,说明这个ApplicationThread也是个Binder服务端的执行者,
        类里写的是接收消息后的执行代码
}

而这个 ActivityThread 我们在学习 Handler 机制的时候知道:在其 main 入口方法开启了主线程的消息循环。
当我们新点开一个应用后,Zygotefork 一个子进程后就会执行 ActivityThreadmain方法。
app.Thread.scheduLeLaunchActivity() 最终执行在 ActvitiyThread 的内部类 ApplicationThread 中。

插播一个小猜想:我们活动A用Intent开启别人应用的活动B,那么活动B其实是运行在活动A所在的进程中的。

但是上述猜测是错误的,因为我用demo试了。。。可是不知道该如何在源码中找到依据。字体加粗警告,上面这段话是错的

然后我们继续上面的来看看 app.thread.scheduleLaunchActivity() 真正的执行调用。如下:

//ActivityThread.java 的内部类 ApplicationThread 中
        // we use token to identify this activity without having to send the
        // activity itself back to the activity manager. (matters more with ipc)
        @Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                ...) {
            ...
            ActivityClientRecord r = new ActivityClientRecord();
            r.token = token;
            r.ident = ident;
            r.intent = intent;
            ...
            sendMessage(H.LAUNCH_ACTIVITY, r);   这儿,看这儿~ LAUNCH_ACTIVITY ~
        }

上面代码中的 LAUNCH_ACTIVITY是不是看着很振奋人心 ~ ,没错,我们最初的 startActivity(new Intent(...)) 方法最后来到了我们的 ActivityThread 中。并且,创建 Activity 的工作也是在这里做的。

从之前的知道 ApplicationThread 类负责执行 Binder 发送过来的指令,所以我们继续观察这个类里头的方法,就会发现和 scheduleLaunchActivity() 非常类似的许多方法,比如:

private class ApplicationThread extends IApplicationThread.Stub {

    public final void scheduleResumeActivity(IBinder token, int processState,...) {
        ...
        sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0, 0, seq);    }
    public final void scheduleNewIntent(List intents, IBinder token,...) {
        ...
        sendMessage(H.NEW_INTENT, data);    }
    public final void scheduleBindService(IBinder token, Intent intent, ...) {
        ...
        sendMessage(H.BIND_SERVICE, s);    }
    public void scheduleRegisteredReceiver(IIntentReceiver receiver,...) ... {
        ...
        receiver.performReceive(intent, ...);        }
    ...
}

嘿嘿是不是很兴奋。Activity 、Service 、BroadcastReceiver 的许多操作这儿都能找到踪影。(由于我并没有用过ContentProvider,所以不知道这儿有没有,各位可以自己看一看。)

另外我们也注意到了,很多方法下面都有个 sendMessage() 的方法。比如说我们的 sendMessage(H.LAUNCH_ACTIVITY, r);,经常用Handler的我们应该也很熟悉了,这个就是发送消息呗。看看发的消息的最后的调用:

//ActivityThread.java中
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    ...
    Message msg = Message.obtain();
    ...
    mH.sendMessage(msg);这个mH看下面
}
--------------mH----------------------
final H mH = new H();  H里面的handleMessage如下:
--------------H----------------------
private class H extends Handler {
    public static final int LAUNCH_ACTIVITY = 100;
    ...
    public void handleMessage(Message msg) {
        ...
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                r.loadedApk = getLoadedApkNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
            case RELAUNCH_ACTIVITY:
            ....   

这个 H 里面的各种 case 就是我们非常熟悉的东西。各位可以自己看看。我们继续来瞅瞅 handleLaunchActivity() 里做了啥:

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

    这里,看这儿。一个Activity被创建了出来
    Activity a = performLaunchActivity(r, customIntent); 
    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;        
        下面这个方法 ~ 最后会调用 Activity 的 onResume 方法 ~ 分析可以见后面
        //所以我们的 onCreate 、 onStart 在哪儿呢,在上面的performLaunch中 ~
        handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
        if (!r.activity.mFinished && r.startsNotResumed) {
            performPauseActivityIfNeeded(r, reason);
            if (r.isPreHoneycomb()) {
                r.state = oldState;
            }
        }
    } else {
        // If there was an error, for any reason, tell the activity manager to stop us.
        上面这个官方注释:如果这儿有错误,不管是什么原因,告诉ActivityManagerService来停止我们。
        所以我们至少知道了,如果要停止Activity需要由自己告诉AMS来停止自己。
        try {
            ActivityManager.getService().finishActivity(r.token,...);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}

接着看 performLaunchActivity() 如下:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        重点之一!我们的Context在这儿创建
        ContextImpl appContext = createBaseContextForActivity(r); 
        Activity activity = null;
        try {
            重点之二!类加载器加载一个类然后创建
            java.lang.ClassLoader cl = appContext.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) {
            ...
        }
        try {
            重点之三!创建Application(当然这里面是有判断的,如果已经存在Application就不会再创建)    
            Application app = r.loadedApk.makeApplication(false, mInstrumentation);
            -----判断的代码如下----
            if (mApplication != null) {
                return mApplication;
            }
            -----如上-------------
            ...
            if (activity != null) {
                ...
                appContext.setOuterContext(activity);

                重点之四!把Activity与context、Application关联起来
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);
                ...

                重点之五!最终会调用我们的 onCreate 方法了~
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                ...

                if (!r.activity.mFinished) {
                    重点之六!最终会调用我们的 onStart 方法了~
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    ...这里的代码和状态储存有关
                }
                if (!r.activity.mFinished) {
                    ... 
                        这个 onPostCreate 方法也挺有意思的。是当Activity彻底运行起来之后回调的
                        在 onStart 之后,在 onResume 之前。观看源码之后才发现还有这么多有趣的东西。
                        这些东西可不是我们平时见到的那张Activity生命周期图里可以看到的
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    ...
                }
            }
            ...
            上面的一系列代码都是mInstrumentation.callActivityxxxxxxx,
            不过在方法里都会调用actvity.xxxxx()。
            就是   :先过去,再回来。
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            ...
        }
        return activity;
}

所以我们知道这个 performLaunchActivity 做了非常多而且非常重要的工作。致敬。

但是这一步我们还看不到界面,因为在 onResume 中才会

DecorView 添加到 WindowManger 中,最后将 ActivityDecorView 设置为可见,并且通知 AMS 渲染视图,所以在 onResume 函数之后, Activity 就显示在屏幕上了。

所以后面这一块我们先放着,可以在讲解 WindowManager、Decorview这些的时候再讲。

这时候我们返回去看。我们一开始讲解的入口是从 startActivity() 开始的,简单总结如下:

我们的 Activity 调用 startActivity 发消息给 AMS ,
然后 AMS 操作了一波 ActivityStackActivityStackSupervisor 后, 发消息给 ActivityThread 的内部类 ApplicationThread
然后 ApplicationThreadHandler 发消息并在 handlerMessage() 中执行 Activity 的创建工作
该工作里包括了 context、application等的创建,当然application如果存在了就不会再创建,而且一般情况下其实application早就被创建了,然后和Activity绑定。
然后将 DecorView 放到 WindowManager 中并通知 AMS 渲染视图,然后我们的 Activity 就可以看到啦。

也就是说我们这套流程的讲解,前提是我们的应用已经启动了。那么我们的应用还没启动的时候是怎么个情况呢?

接下来请看:

--------------------点击APP图标打开一个新应用的流程--------------------------

自己去找跳转的感觉简直恐怖啊。。。这么纷繁的字母组成了如此复杂的系统。。。所以只好跟着别人的文章来走了。。。如下:

https://blog.csdn.net/itachi85/article/details/64123035

https://blog.csdn.net/itachi85/article/details/55047104

https://blog.csdn.net/freekiteyu/article/details/79318031

//大概直接看最后一个博客就可以了。。。。

看应用启动的源码快疯了。。。

你可能感兴趣的:(中道崩阻——Activity启动源码学习记录)