Activity的启动流程(二):应用进程部分

接上篇: Activity的启动流程(一):ActivityManagerService部分java

上一篇咱们分析了activity在AndroidManagerService部分的启动流程,这一篇咱们再来看一下activity在应用进程部分的启动流程。学习activity在应用进程部分的启动流程对于咱们深刻理解android应用的工做原理,特别是学习一些插件化方面的知识是颇有帮助的,由于上一篇中介绍的启动流程大部分位于AMS中,AMS是一个系统服务进程,咱们没法对其进行修改,而本篇介绍的启动流程则位于应用进程中,咱们能够利用反射等技术手段对其进行修改,某些插件化技术的核心原理就是经过对这部分的代码进行hook,以达到替换要启动的activity的目的。android

1.分发启动新activity的事件

在上一篇的结尾处咱们能够看到,AMS最后调用了ActivityThread的scheduleLaunchActivity方法,activity的启动流程从AMS进程进入到了应用进程:缓存

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                    r.persistentState, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profilerInfo);
复制代码

咱们来看一下ActivityThread中的scheduleLaunchActivity方法:markdown

源码路径:\frameworks\base\core\java\android\app\ActivityThread.java

    @Override
    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<ResultInfo> pendingResults, List<ReferrerIntent> 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);
    }
复制代码

在scheduleLaunchActivity方法中,将接收到的参数都封装到了一个ActivityClientRecord对象中。从名字就能够看出,ActivityClientRecord是activity在客户端的一个记录,主要封装了activity的一些相关信息。app

在scheduleLaunchActivity方法的最后调用了sendMessage方法发送了一个消息,咱们来看一下sendMessage方法:async

private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }
复制代码

能够看到sendMessage方法就是构建了一个Message对象,并经过mH这个对象进行了发送。很明显mH是一个Handler对象,这里是使用的Android的消息机制来进行消息分发。mH是一个类名为H的实例,而H则继承自Handler。mH主要用来处理主线程中的一些事件。使用消息机制来进行activity的启动能够保证Activity的启动是在主线程中进行的。该消息最终会被mH的handleMessage方法进行处理,源码以下:ide

private class H extends Handler {

        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, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                ...
            }
            ...
        }
    }
复制代码

在handleMessage方法中,首先调用了getPackageInfoNoCheck,并将返回值赋值给了r的packageInfo变量。getPackageInfoNoCheck返回的是一个LoadedApk对象,该对象主要封装了一些APK相关的信息。以后系统又调用了handleLaunchActivity方法来进一步进行activity的启动。oop

先来看一下getPackageInfoNoCheck方法的代码:post

private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode, boolean registerPackage) {
        final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
        synchronized (mResourcesManager) {
            WeakReference<LoadedApk> ref;
            if (differentUser) {
                ref = null;
            } else if (includeCode) {
                // 注释1:查看是否有缓存
                ref = mPackages.get(aInfo.packageName);
            } else {
                ref = mResourcePackages.get(aInfo.packageName);
            }

            LoadedApk packageInfo = ref != null ? ref.get() : null;
            if (packageInfo == null || (packageInfo.mResources != null
                    && !packageInfo.mResources.getAssets().isUpToDate())) {
                ...
                //注释2:若是没有缓存,则建立新LoadedApk对象
                packageInfo =
                    new LoadedApk(this, aInfo, compatInfo, baseLoader,
                            securityViolation, includeCode &&
                            (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);

                ...

                if (differentUser) {
                    // Caching not supported across users
                } else if (includeCode) {
                    // 注释3:将LoadedApk对象放入缓存
                    mPackages.put(aInfo.packageName,
                            new WeakReference<LoadedApk>(packageInfo));
                } else {
                    mResourcePackages.put(aInfo.packageName,
                            new WeakReference<LoadedApk>(packageInfo));
                }
            }
            return packageInfo;
        }
    }
复制代码

首先,在注释1处,先尝试从mPackages对象中获取这个LoadedApk对象,若是获取不到的话,则会在注释2处建立一个新的LoadedApk对象,并在注释3处将这个LoadedApk加入到mPackages中。学习

咱们再来看一下handleLaunchActivity方法的代码:

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

        // 注释1:初始化WindowManager,经过Binder获取WindowServiceManager的本地代理
        WindowManagerGlobal.initialize();

        // 注释2:建立Activity
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            // 注释3
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

           ...
        }
        ...
    }
复制代码

在注释1处,经过调用 WindowManagerGlobal.initialize()来对WindowManager进行了初始化,WindowManger是WindowManagerService在客户端的一个代理对象,而WindowManagerService与ActivityManagerService相似,也是一个系统服务,主要用来对窗口的显示进行控制。客户端经过WindowManger对象,利用Binder机制来与WindowManagerService进行通讯。

在注释2处经过performLaunchActivity来建立了Activity的实例,至此咱们要启动的Activity实例终于被建立出来了。

在注释3处则调用了handleResumeActivity方法使activity进入resume状态。

下面咱们来看一下performLaunchActivity和handleResumeActivity具体对activity作了哪些初始化工做。

2.activity的初始化

performLaunchActivity方法的源码以下:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

        ...

        ComponentName component = r.intent.getComponent();
        ...

        // 注释1:为activity建立context
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();

            // 注释2:建立activity实例
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            ...
        } ...

        try {
            ...
            if (activity != null) {
                ...
                appContext.setOuterContext(activity);
                // 注释3
                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);

                ...
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                // 设置主题
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                // 注释4:调用activity的OnCreate方法
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    //注释5:进入start状态
                    activity.performStart();
                    r.stopped = false;
                }
                ...
            }
            r.paused = true;

            mActivities.put(r.token, r);

        } ...

        return activity;
    }
复制代码

在注释1处,系统首先为activity建立了context对象,并经过这个context对象获取了一个ClassLoader,用于加载要启动的activity。

在注释2处,经过调用mInstrumentation的newActivity方法建立了activity的实例。

在注释3处调用了activity的attach方法来对activity进行一些初始化工做。

在注释4处调用了mInstrumentation的callActivityOnCreate方法,从这个方法的名字就能够看出,该方法内部调用了activity的onCreate方法。

在注释5处调用了activity的performStart()方法,使activity进入start状态。

咱们首先来看mInstrumentation的newActivity方法:

源码路径:\frameworks\base\core\java\android\app\Instrumentation.java public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }
复制代码

newActivity方法只有一行代码,就是经过反射加载了要启动的activity类并建立了一个实例对象。

咱们再来看一下activity的attach方法作了哪些初始化工做:

源码路径:\frameworks\base\core\java\android\app\Activity.java final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        // 注释1:为activity建立window对象
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        //设置软键盘状态模式
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }

        // 注释2:初始化一些成员变量
        mUiThread = Thread.currentThread();
        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }

        // 注释3:为window设置windowManager
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);
    }
复制代码

在注释1处为该activity建立了一个window对象,能够看到这个window对象实际上是一个PhoneWindow对象。在Android系统中,每一个Activity都对应一个window对象,window主要和activity的窗口显示有关。

在注释2处为该activity初始化了一些成员变量,如主线程、ui线程、application对象等。

在注释3处为window设置了WindowManager对象。

看完了activity的attach方法,咱们再来看Instrumentation的callActivityOnCreate方法:

源码路径:\frameworks\base\core\java\android\app\Instrumentation.java public void callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
    }
复制代码

能够看到在callActivityOnCreate方法中又调用了activity.performCreate来进一步初始化activity。performCreate方法的源码以下:

源码路径:\frameworks\base\core\java\android\app\Activity.java final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        restoreHasCurrentPermissionRequest(icicle);
        // 注释1:调用onCreate
        onCreate(icicle, persistentState);
        mActivityTransitionState.readState(icicle);
        // 注释2
        performCreateCommon();
    }
复制代码

在注释1处直接调用了onCreate方法,咱们一般会重写activity的onCreate方法来进行一些自定义的初始化工做。在注释2处又调用了performCreateCommon方法,咱们来看一下该方法的源码:

final void performCreateCommon() {
        mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
                com.android.internal.R.styleable.Window_windowNoDisplay, false);
        mFragments.dispatchActivityCreated();
        mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
    }
复制代码

能够看到在performCreateCommon方法中调用了mFragments的dispatchActivityCreated方法,该方法内部会通知activity内的相关fragment,并触发这些fragment的onActivityCreated方法。


回到ActivityThread的handleLaunchActivity方法中。在分析完performLaunchActivity方法后,咱们再来看一下handleResumeActivity方法作了哪些工做。handleResumeActivity方法代码以下:

源码路径:\frameworks\base\core\java\android\app\ActivityThread.java final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        
        ...

        // 注释1
        r = performResumeActivity(token, clearHide, reason);

        if (r != null) {
            final Activity a = r.activity;

            ...

            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                ...
            } else if (!willBeVisible) ...

            cleanUpPendingRemoveWindows(r, false /* force */);

            if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
                ...
                WindowManager.LayoutParams l = r.window.getAttributes();
                ...
            }

            ...

            // 通activity manager该activity已经处于resumed状态
            if (reallyResume) {
                try {
                    ActivityManager.getService().activityResumed(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }

        } else {
            ...
        }
    }
复制代码

handleResumeActivity方法的代码很长,可是咱们不用纠结于代码细节。在注释1处调用了performResumeActivity,后面的代码都是一些与window、decorView、windowManager相关的操做,不难猜出是与activity的显示有关,咱们在这里就不深刻分析了。咱们主要来看一下performResumeActivity方法:

public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        if (localLOGV) Slog.v(TAG, "Performing resume of " + r
                + " finished=" + r.activity.mFinished);
        if (r != null && !r.activity.mFinished) {
            ...
            try {
               ...
                r.activity.performResume();

                ...
            } ...
        }
        return r;
    }
复制代码

performResumeActivity方法主要是调用了activity的performResume方法:

final void performResume() {
        ...

        //调用activity的onResume方法
        mInstrumentation.callActivityOnResume(this);
        ...

        //通知fragment进入Resume状态
        mFragments.dispatchResume();
        mFragments.execPendingActions();

        ...
    }
复制代码

首先,系统调用了mInstrumentation的callActivityOnResume,在callActivityOnResume方法内部会直接调用activity的onResume方法,这点与以前调用onCreate方法比较类似,这里就再也不进一步分析了。这样,activity就进入生命周期的Resume阶段了。

总结

咱们对这部分的activity启动流程进行一下总结:

  1. AMS调用ActivityThread的scheduleLaunchActivity方法,启动流程从AMS进入应用进程
  2. ActivityThread经过消息机制分发启动activity的事件,确保activity的启动处于主线程中。
  3. 经过反射建立activiy实例,并对该实例进行一些初始化工做
  4. 该activity开始了它的生命周期,分别调用了onCreate、onStart、onResume方法,最终显示在屏幕上。

至此activity的建立流程就分析完了,本人水平有限,若是有哪里写的很差还望各位大佬多多指点。关于启动流程中应用进程的建立部分并无在这里进行介绍,由于这部份内容比较多,以后会单独写一篇文章介绍应用进程的建立流程。

相关文章
相关标签/搜索