Android:图解Activity启动流程源码(整体流程)

Posted 鸽一门

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android:图解Activity启动流程源码(整体流程)相关的知识,希望对你有一定的参考价值。

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

以上代码对于android开发者再熟悉不过了,功能即启动 TextActivity。这是最基本的Intent使用知识,通过显示Intent来触发 Activity的启动,而Activity,四大组件中的老大,是一种展示型组件,用于向用户展示交互界面,如此重要的一个角色,类似于以上的代码,每天都在写,可是有几个问题是否想过:

  • 系统内部是如何启动一个Activity?
  • 当启动一个新Activity时,该对象是在何时创建的?
  • Application 的onCreate方法又是在何时被系统回调?
  • Activity 的onCreate方法又是在何时被系统回调?

接下来从源码的角度来分析解决以上问题,注意:由于Android内部实现比较复杂,所以以下分析更侧重于整体流程,对Activity启动建立一个整体的意识。



一. Activity启动流程步骤

Step 1. 启动Activity

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


Step 2. Activity的startActivityForResult 方法

Activity的启动调用的就是startActivity方法,此方法有多种重载方式,但最后都会调用 startActivityForResult 方法,实现如下:

【Activity 类】

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());
            
            if (requestCode >= 0) 
                //
                mStartedActivity = true;
            

            ......
         else 
            ......
        
    

以上代码中第一行 if判断 mParent == null 即可,mParent 代表的是ActivityGroup,它最开始用来在一个界面中嵌入多个子Activity,而在API13中已经被抛弃了,因为Fragment的出现和它的高效,已经代替了ActivityGroup

其中还要注意if判断语句中的一个参数 mMainThread.getApplicationThread(),它的类型为 ApplicationThread,而ApplicationThread 是 ActivityThread的一个内部类。(通过后面分析可知,这两个类在Activity的启动过程中起重要作用)



Step 3. Instrumentation的execStartActivity方法

介绍两个基本点后,接下来查看InstrumentationexecStartActivity 方法。

【Instrumentation 类】

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) 
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) 
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        
        if (mActivityMonitors != null) 
                ......
            
        
        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 方法来完成,往下深入之前,先介绍一下此类相关知识:ActivityManagerService(简称AMS)继承自ActivityManagerNative,而ActivityManagerNative继承自Binder并实现了IActivityManager的具体实现。

接下来查看ActivityManagerNative的getDefault() 方法:

【ActivityManagerNative 类】

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

以上代码可知: 而 ActivityManagerNative.getDefault()其实是一个IActivityManager类型的Binder对象,因此它的具体实现是ActivityManagerService类!而且在ActivityManagerNative类实现中,AMS此Binder对象采用Singleton单例模式对外提供。



Step 4. ActivityManagerService的startActivity方法

根据以上分析后,由原来Activity是 ActivityManagerNative.getDefault()来启动,转移到了AMS!继续深入,直接查看AMS的startActivity方法:

【ActivityManagerService类】

        @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags,
            String profileFile, ParcelFileDescriptor profileFd, Bundle options) 
             //☆☆☆☆☆  重点!!!!!
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode,
                startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
    

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags,
            String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) 
            .....
             //☆☆☆☆☆  重点!!!!!
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
                null, null, options, userId);
    

可以看出Activity的启动过程又转移到了 ActivityStackSupervisor的 startActivityMayWait方法中。但是继续往下深入之前先暂停一会,以上步骤用时序图画出来理清一下思路:



Step 5. ActivityStackSupervisor 和 ActivityStack 之间互相调用

当Activity的启动过程又转移到了 ActivityStackSupervisor后,此类不断调用自身方法并且与 ActivityStack 之间的方法回调。但是,这涉及到的方法略多,而这篇博文作为认识整体流程,就不贴相关代码了,重点不同,将两个类之间的方法回调以流程图展示,更清晰,下面会直接讲解重点方法:

以上流程图是ActivityStackSupervisor 和 ActivityStack 之间的互相调用,了解基本流程即可,这里直接看此过程的最后一个调用方法:realStartActivityLocked

【ActivityStackSupervisor 类】

    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,
                    new Configuration(mService.mConfiguration), r.compat,
                    app.repProcState, r.icicle, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profileFile, profileFd,
                    profileAutoStop);

            ......
            

以上这行代码很重要,正式转移了Activity启动过程,其中需要详细介绍app.thread,它的类型就是IApplicationThread。



Step 6. ApplicationThreadNative内部类 ApplicationThreadProxy

IApplicationThread源码实现如下:

【IApplicationThread 类】

public interface IApplicationThread extends IInterface 
    void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,
            int configChanges) throws RemoteException;
    void scheduleStopActivity(IBinder token, boolean showWindow,
            int configChanges) throws RemoteException;
    void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
    void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;
    void scheduleResumeActivity(IBinder token, int procState, boolean isForward)
            throws RemoteException;
    void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
    void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
            int procState, Bundle state, List<ResultInfo> pendingResults,
            List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
            String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler)
            throws RemoteException;
    void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
            List<Intent> pendingNewIntents, int configChanges,
            boolean notResumed, Configuration config) throws RemoteException;
    void scheduleNewIntent(List<Intent> intent, IBinder token) throws RemoteException;
    void scheduleDestroyActivity(IBinder token, boolean finished,
            int configChanges) throws RemoteException;
    void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,
            int resultCode, String data, Bundle extras, boolean sync,
            int sendingUser, int processState) throws RemoteException;
    static final int BACKUP_MODE_INCREMENTAL = 0;
    static final int BACKUP_MODE_FULL = 1;
    static final int BACKUP_MODE_RESTORE = 2;
    static final int BACKUP_MODE_RESTORE_FULL = 3;
    void scheduleCreateBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo,
            int backupMode) throws RemoteException;
    void scheduleDestroyBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo)
            throws RemoteException;
    void scheduleCreateService(IBinder token, ServiceInfo info,
            CompatibilityInfo compatInfo, int processState) throws RemoteException;
    void scheduleBindService(IBinder token,
            Intent intent, boolean rebind, int processState) throws RemoteException;
    void scheduleUnbindService(IBinder token,
            Intent intent) throws RemoteException;
    void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
            int flags, Intent args) throws RemoteException;
    void scheduleStopService(IBinder token) throws RemoteException;
            ......

因为IApplicationThread 类继承了 IInterface接口,所以它是一个Binder类型的接口。从IApplicationThread 声明的接口可以看出,其内部包含了大量启动、停止Activity的接口,此外还包含了启动和停止服务的接口,IApplicationThread 这个 Binder接口实现者完成了大量和Activity、Service启动/停止有关的功能。

可是IApplicationThread 的实现者到底是什么?

答案就是 ActivityThread 中的内部类 ApplicationThread。来查看一下ApplicationThread的定义:

 private class ApplicationThread extends ApplicationThreadNative 
         .....
         

 public abstract class ApplicationThreadNative extends Binder
        implements IApplicationThread 
        ......
        

由以上代码可以看出 ApplicationThread 继承了 ApplicationThreadNative ,而ApplicationThreadNative 继承了Binder并且实现了IApplicationThread 接口,但是在它内部,还有一个内部类ApplicationThreadProxy,实现如下:

【ApplicationThreadProxy 类】

class ApplicationThreadProxy implements IApplicationThread 
    private final IBinder mRemote;

    public ApplicationThreadProxy(IBinder remote) 
        mRemote = remote;
    

    public final IBinder asBinder() 
        return mRemote;
    

    //☆☆☆☆☆  重点!!!!!
    public final void schedulePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges) throws RemoteException 
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        data.writeInt(finished ? 1 : 0);
        data.writeInt(userLeaving ? 1 :0);
        data.writeInt(configChanges);
        mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    

    public final void scheduleStopActivity(IBinder token, boolean showWindow,
            int configChanges) throws RemoteException 
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        data.writeInt(showWindow ? 1 : 0);
        data.writeInt(configChanges);
        mRemote.transact(SCHEDULE_STOP_ACTIVITY_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    

    ......

ApplicationThreadProxy 也是系统为AIDL文件自动生成的代理类。

通过以上分析可知,ApplicationThreadNative就是IApplicationThread的实现者,由于ApplicationThreadNative被系统定义为抽象类,所以ApplicationThread就成了IApplicationThread的最终实现者。



Step 7. ActivityThread 内部类 ApplicationThread

绕了一大圈,Activity的启动过程最终回到了ApplicationThread ,它通过 scheduleLaunchActivity方法来启动 Activity,代码如下:

 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
                int procState, Bundle state, List<ResultInfo> pendingResults,
                List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
                String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) 

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;

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

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

            r.profileFile = profileName;
            r.profileFd = profileFd;
            r.autoStopProfiler = autoStopProfiler;
            updatePendingConfiguration(curConfig);

            //☆☆☆☆☆  重点!!!!!
            queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
        

在 ApplicationThread中,此方法实现非常简单,就是发送一个Activity的消息交由 Handle 处理(最后一行代码),这个Handle实现于 ActivityThread 内部,名为H。



Step 8. ActivityThread 内部 Handle

此Handle对消息处理的实现:

      public static final int LAUNCH_ACTIVITY         = 100;
        public static final int PAUSE_ACTIVITY          = 101;
        public static final int PAUSE_ACTIVITY_FINISHING= 102;
        public static final int STOP_ACTIVITY_SHOW      = 103;
        public static final int STOP_ACTIVITY_HIDE      = 104;
        public static final int SHOW_WINDOW             = 105;
        public static final int HIDE_WINDOW             = 106;
        public static final int RESUME_ACTIVITY         = 107;
        ......

        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");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;

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

                    //☆☆☆☆☆  重点!!!!!
                    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;
                    ......
                    
           

非常熟悉的Handle实现方法,注意在ApplicationThread发送消息的标志是H.LAUNCH_ACTIVITY,直接查看handleMessage方法中对应的处理代码。此时可以发现,Activity的启动过程是由ActivityThreadhandleLaunchActivity方法实现,查看其代码:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) 
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();

        if (r.profileFd != null) 
            mProfiler.setProfiler(r.profileFile, r.profileFd);
            mProfiler.startProfiling();
            mProfiler.autoStopProfiler = r.autoStopProfiler;
        

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

         //☆☆☆☆☆  重点!!!!!
        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);

            ......
        
    

总算到了最后一步,从以上代码可以看出,performLaunchActivity方法最终完成了Activity对象的创建和启动过程,并且ActivityThread通过 handleResumeActivity方法来调用被启动Activity的onResume这一生命周期方法。

后半部分时序图如下:



接下来详细介绍performLaunchActivity方法完成的五大事件:

(1)从ActivityClientRecord中获取待启动的Activity的组件信息

【ActivityThread 类的 performLaunchActivity方法中】

        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) 
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    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);
        

(2)从Instrumentation 的 newActivity 方法使用类加载器创建 Activity对象

【ActivityThread 类的 performLaunchActivity方法中】

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

至于 Instrumentation 的 newActivity,它的实现比较简单,就是通过类加载器创建Activity对象,代码如下:

【Instrumentation 类】

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

(3)通过 LoadedAPK 的 makeApplication 方法来尝试创建 Application对象

【ActivityThread 类的 performLaunchActivity方法中】

  Application app = r.packageInfo.makeApplication(false, mInstrumentation);

查看LoadedAPK 的 makeApplication 方法具体实现:

【LoadedAPK 类】

    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();
            ContextImpl appContext = new ContextImpl();
            appContext.init(this, null, mActivityThread);
            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;
    

从此方法的实现可以看出,如果Application已经被创建过,就不会再创建,以为者一个应用只有一个Application对象。Application对象的创建也是通过Instrumentation完成的,这个过程和Activity对象的创建一样,都是通过类加载器实现的。Application创建完毕后,系统会通过 Instrumentation 的 callApplicationOnCreate 来调用Application的 onCreate 方法。


(4)通过 ContextImpl对象并通过Activity的 attach 方法来完成一些重要数据的初始化

【ActivityThread 类的 performLaunchActivity方法中】

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

ContextImpl是一个很重要的数据结构,它是Context 的具体实现,Context中大部分逻辑都是由ContextImpl来实现的。ContextImpl是通过Activity的attach方法来和Activity建立关系的,除此之外,在attach方法中Activity还会完成Window的创建并建立自己和Window的关联,这样当Window接收到外部输入事件后就可以将事件传递给Activity。


(5)调用 Activity 的 onCreate方法

【ActivityThread 类的 performLaunchActivity方法中】

mInstrumentation.callActivityOnCreate(activity, r.state);

如上代码,Activity的onCreate方法被调用,意味着Activity已经完成了整个启动过程!




二. Activity启动流程总时序图:



其实以上关于Activity底层的问题你不知道也可以写好代码,但是学习了解系统的底层工作原理,相当于学习Android操作系统,可以提高我们对操作系统在技术实现上的理解。如果学习Android使用方法相当于练习武功招式,那么学习底层工作原理就相当于修炼内功,haha,要知道高手之间过招比的是什么? 当然是看谁内功深厚啦~

最后,在此声明,以上内容总结于《Android艺术开发与探索》,时序图是自己归纳的,这个我参考了网上其它的博文讲解,但是跟书上稍有差别,大概是讲解的侧重点不同,如有错误,还请指正。

关于书上这个章节我看过起码5遍,但每次过了不久就忘了,所以此次总结下来,印象深刻一些,但是我感觉自己还是没有完全理解,只是了解了一个大致流程,以后再做补充吧。

检验一个知识点是否学会,写下来和讲出来恐怕是最有效的方法了。

希望对你们有帮助 :)
共同学习

以上是关于Android:图解Activity启动流程源码(整体流程)的主要内容,如果未能解决你的问题,请参考以下文章

Android Activity启动流程源码解析

Android Activity启动流程源码解析

Android 启动过程Activity 启动源码分析 ( ActivityThread 流程分析 二 )

framework之Activity启动流程(基于Android11源码)

framework之Activity启动流程(基于Android11源码)

framework之Activity启动流程(基于Android11源码)