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 gDefault = new Singleton() {        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方法中。但是继续往下深入之前先暂停一会,以上步骤用时序图画出来理清一下思路:

Android:图解Activity启动流程源码(整体流程)_第1张图片



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

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

Android:图解Activity启动流程源码(整体流程)_第2张图片

以上流程图是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 results) throws RemoteException;    void scheduleLaunchActivity(Intent intent, IBinder token, int ident,            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,            int procState, Bundle state, List pendingResults,            List pendingNewIntents, boolean notResumed, boolean isForward,            String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler)            throws RemoteException;    void scheduleRelaunchActivity(IBinder token, List pendingResults,            List pendingNewIntents, int configChanges,            boolean notResumed, Configuration config) throws RemoteException;    void scheduleNewIntent(List 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 pendingResults,                List 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这一生命周期方法。

后半部分时序图如下:

Android:图解Activity启动流程源码(整体流程)_第3张图片



接下来详细介绍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启动流程总时序图:

Android:图解Activity启动流程源码(整体流程)_第4张图片



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

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

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

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

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

更多相关文章

  1. Android中获取控件宽高的4大方法
  2. Android 6.0开发实现关机菜单添加重启按钮的方法
  3. google被墙后,Android SDK下载和更新失败的解决方法!
  4. HierarchyView的实现原理和Android设备无法使用HierarchyView的
  5. SONY 系列手机 Android 5.1 系统 Root 方法
  6. [置顶] 教程--Android SDK更新方法(2016.10.11更新)
  7. 关于Android Studio第一次启动的Fetching android sdk component

随机推荐

  1. 适配Android(安卓)7.0出现读取外部存储问
  2. iOS & Android(安卓)摄像头渲染比较
  3. 【Android多媒体】Android5.0 NuPlayer多
  4. Android中SQLite学习小结
  5. Android支付接入(七):Google In-app-Billing
  6. 完美解决 Failed to fetch URL https://d
  7. 简单实用的安卓原生底部tab实现ViewPager
  8. android中的画笔类paint
  9. android RSS解析器创建步骤
  10. android使用NDK编译curl库