Framework之Activity 启动过程详解

时间:2021-10-12 04:33:30

Activity 在我们应用程序的开发当中经常用到,我们可以通过下面代码启动一个Activity。

        Intent intent = new Intent(this,FirstActivity.class);
        startActivity(intent);

上面代码很简单,调用Android SDK API ,但是我们不知道系统底层的工作原理。我们要成为高级工程师或者架构师我们必须要了解这些。我们在阅读时注意把握整体流程,不要太深入代码细节。
推荐2个在线阅读源码的网站,个人比较喜欢用第二个。
1 http://androidxref.com
2 http://www.grepcode.com/
我们先来看一张Activity启动过程的流程图,方便我们理解源码,掌握整体流程。

Framework之Activity 启动过程详解
下面我们就根据流程图来看源码,源码是Android5.0版本。

1 分析 startActivityForResult

下面我们就从startActivity来开始分析,Activity 有许多重载方法。最后都会调用startActivityForResult方法

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);
              //省略 
            }

         //省略
        } else {
           //省略
        }
    }
  • 这里的mInstrumentation是Activity类的成员变量,它的类型是Intrumentation,它用来监控应用程序和系统的交互。
  • 我们需要注意mMainThread.getApplicationThread() 这个参数,它的类型是ApplicationThread,ApplicationThread是ActivityThread内部类,它是一个Binder对象,后面我们会看到,ActivityManagerService会使用它来和ActivityThread来进行进程间通信。
  • mToken也是Activity类的成员变量,它是一个Binder对象的远程接口。
    下面看一下 Instrumentation 的execStartActivity方法

2 分析 Instrumentation 的execStartActivity方法

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        //省略
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManagerNative.getDefault()
                .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;
    }

由上面代码可以看出启动Activity的真正实现是由ActivityManagerNative.getDefault() .startActivity方法完成。

public abstract class ActivityManagerNative extends Binder implements IActivityManager

ActivityManagerNative 继承自Binder实现了IActivityManager接口是一个抽象类。ActivityManagerService(简称AMS)继承自ActivityManagerNative,ActivityManagerNative.getDefault()是IActivityManager类型的Binder对象。下面看一下ActivityManagerNative.getDefault()代码。

    static public IActivityManager getDefault() {
        return gDefault.get();
    }
  private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

        static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

从上面代码我们可以看出 这里的gDefault 采用单例模式对外提供IActivityManager对象,我们在create()方法中调用asInterface()方法在,接着在asInterface()方法中调用new ActivityManagerProxy(obj)。ActivityManagerNative.getDefault返回ActivityManagerService的远程接口,即ActivityManagerProxy接口.下面我们来看一下ActivityManagerProxy的startActivity方法代码

3 分析ActivityManagerProxy的startActivity方法

class ActivityManagerProxy implements IActivityManager { public ActivityManagerProxy(IBinder remote) { mRemote = remote; } public IBinder asBinder() { return mRemote; } 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; } }

ActivityManagerProxy是ActivityManagerService的远程接口,通过 mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);方法将参数传到AMS中。后面我们就继续分析ActivityManagerService.startActivity。

4 分析ActivityManagerService的startActivity方法

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, 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 options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, userId, null, null);
    }

从上面的代码可以看出 ActivityManagerService的startActivity方法中调用startActivityAsUser()方法,在startActivityAsUser()方法中调用mStackSupervisor.startActivityMayWait();下面我们分析一下mStackSupervisor.startActivityMayWait()方法。

5 分析mStackSupervisor.startActivityMayWait()方法

Activity 的启动过程转移到 ActivityStackSupervisor.startActivityMayWait()方法,在startActivityMayWait方法中调用startActivityLocked方法,在startActivityLocked方法中调用startActivityUncheckedLocked方法,在startActivityUncheckedLocked方法中调用resumeTopActivitysLocked方法,在resumeTopActivitysLocked方法中调用ActivityStack的resumeTopActivityLocked方法,在resumeTopActivityLocked方法中调用resumeTopActivityInnerLocked方法,在resumeTopActivityInnerLocked方法中调用ActivityStackSupervisor的startSpecificActivityLocked方法,在startSpecificActivityLocked中调用realStartActivityLocked方法,下面我们看一下realStartActivityLocked方法中这段代码

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

app.thread的类型为 IApplicationThread, IApplicationThread是一个接口,ApplicationThreadNative继承了Binder实现了IApplicationThread接口,但是ApplicationThreadNative是个抽象的类,ApplicationThread继承了ApplicationThreadNative,所以ApplicationThread是真正的实现类。ApplicationThreadNative有个内部类ApplicationThreadProxy,实现了IApplicationThread接口,
这里最终通过app.thread进入到ApplicationThreadProxy的scheduleLaunchActivity方法中。

public abstract class ApplicationThreadNative extends Binder implements IApplicationThread private class ApplicationThread extends ApplicationThreadNative ApplicationThreadProxy implements IApplicationThread

我们来看一下ApplicationThreadProxy的scheduleLaunchActivity方法

    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
            IVoiceInteractor voiceInteractor, int procState, Bundle state,
            PersistableBundle persistentState, List<ResultInfo> pendingResults,
            List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
            ProfilerInfo profilerInfo) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        intent.writeToParcel(data, 0);
        data.writeStrongBinder(token);
        data.writeInt(ident);
        info.writeToParcel(data, 0);
        curConfig.writeToParcel(data, 0);
        compatInfo.writeToParcel(data, 0);
        data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null);
        data.writeInt(procState);
        data.writeBundle(state);
        data.writePersistableBundle(persistentState);
        data.writeTypedList(pendingResults);
        data.writeTypedList(pendingNewIntents);
        data.writeInt(notResumed ? 1 : 0);
        data.writeInt(isForward ? 1 : 0);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }

这个方法最终通过Binder进入到ApplicationThread的scheduleLaunchActivity方法中。

在realStartActivityLocked方法中调用ApplicationThread的scheduleLaunchActivity方法.

6 分析ApplicationThread的scheduleLaunchActivity方法

ApplicationThread是ActivityThread的一个内部类.

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

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            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;

            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

scheduleLaunchActivity 方法首先创建一个ActivityClientRecord实例,并且初始化它的成员变量,然后调用ActivityThread类的sendMessage方法进一步处理。看一下源码

   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方法中调用了mH.sendMessage(msg)方法。mH的类型是H ,它是ActivityThread的内部类,继承Handler。
private class H extends Handler

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {

                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);

                } break;

这里最后调用ActivityThread类的handleLaunchActivity方法进一步处理。

7 分析ActivityThread类的handleLaunchActivity方法

 private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);

           ...
            }
        } else {
             ...
            }
        }
        ...
    }

从上面源码可以看出首先调用performLaunchActivity()方法来完成Activity对象的创建,并调用Activity生命周期的onCreate方法,然后通过调用handleResumeActivity()方法来调用Activity的生命周期的onResume方法。下面我们来分析一下performLaunchActivity方法。

8 分析ActivityThread类的performLaunchActivity方法

8.1
   ActivityInfo aInfo = r.activityInfo;
   if (r.packageInfo == null) {
        r.packageInfo = getPackageInfo(aInfo.applicationInfo,
                Context.CONTEXT_INCLUDE_CODE);
   }

   ComponentName component = r.intent.getComponent();
   if (component == null) {
       component = r.intent.resolveActivity(
           mInitialApplication.getPackageManager());
       r.intent.setComponent(component);
   }

   if (r.activityInfo.targetActivity != null) {
       component = new ComponentName(r.activityInfo.packageName,
               r.activityInfo.targetActivity);
   }

上面源码中的 r 是ActivityClientRecord类型,上面源码主要作用是从ActivityClientRecord中获取待启动Activity相关信息主要是Package 和ComponentName相关信息。

8.2 通过Instrumentation的newActivity方法创建Activity对象
   Activity activity = null;
   try {
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    activity = mInstrumentation.newActivity(
        cl, component.getClassName(), r.intent);
    r.intent.setExtrasClassLoader(cl);
    if (r.state != null) {
        r.state.setClassLoader(cl);
    }
   } catch (Exception e) {
    ......
   }

通过Instrumentation.newActivity 方法创建Activity对象。我们来看一下Instrumentation 的newActivity具体实现。

    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }

通过类加载器和反射来创建Activity对象。

8.3 通过LoadedApk的makeApplication方法来创建Application对象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);

通过LoadedApk的makeApplication方法来创建Application对象,我们来看makeApplication方法具体实现

    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Application app = null;

        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                initializeJavaContextClassLoader();
            }
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + ": " + e.toString(), e);
            }
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;

        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!instrumentation.onException(app, e)) {
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
        }

        ...
        }

        return app;
    }

从上面源码可以看出首先对 mApplication 做了一个判断如果已经创建就不在创建,所以一个应用只会有一个Application。下面我们来看创建流程
1. 获取类加载器
2. 首先创建AppContext对象
3. 然后通过Instrumentation的newApplication方法创建Application对象

下面就看一下Instrumentation的newApplication方法具体实现

   static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }

通过类加载器和反射来创建Application对象。创建完成后执行Application的attach方法

8.4 调用Activity的attach方法初始化一些数据信息
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.voiceInteractor);

从上面源码看出 首先创建Activity的context,然后创建标题和配置信息
ContextImpl.createActivityContext(this, r.packageInfo, r.token);ContextImpl是Context具体实现。

下面我们看一下Activity的attach源码

    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, IVoiceInteractor voiceInteractor) {
        attachBaseContext(context);

        mFragments.attachActivity(this, mContainer, null);

        mWindow = PolicyManager.makeNewWindow(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);
        }
        mUiThread = Thread.currentThread();

        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        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());
            }
        }

        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;
    }

从上面源码可以看出 attach方法主要功能 创建Window并让Window与Activity建立关联。ContextImpl也是通过Activity的attach 方法与Activity建立关联的。

8.5调用Activity的onCreate方法

mInstrumentation.callActivityOnCreate(activity, r.state);
这里不是直接调用Activity的onCreate函数,而是通过mInstrumentation的callActivityOnCreate函数来间接调用,mInstrumentation在这里的作用是监控Activity与系统的交互操作,相当于是系统运行日志。

    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }

这2个方法prePerformCreate(activity) postPerformCreate监控Activity,activity.performCreate(icicle);中会执行Activity的onCreate方法。到这里Activity启动流程已经结束了。