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遍,但每次过了不久就忘了,所以此次总结下来,印象深刻一些,但是我感觉自己还是没有完全理解,只是了解了一个大致流程,以后再做补充吧。

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

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

更多相关文章

  1. 第一行代码 第三章 RecyclerView
  2. 八款Android(安卓)开发者必备的小工具
  3. Android(安卓)4.0.3 联系人(通讯录)应用源码学习
  4. OpenJDK将对Android开发产生怎样的影响?
  5. View基础知识总结
  6. 下载AOSP android源码(最小最快下载方式,跳过编译直接导入Android(
  7. 深入讲解WebView——下
  8. [Android][转]Android(安卓)View绘制13问13答
  9. Android彻底退出应用程序(转)

随机推荐

  1. Android中mpchartlib柱状图的详细属性以
  2. Android的android:clipChildren属性
  3. android 按钮点击的两种方法以及长按事件
  4. Android开发视频教程大总结—23部视频教
  5. Android版块开发资源大汇总
  6. 启动app闪屏问题以及Android自带主题
  7. Android之layout属性介绍
  8. 玩转Android---UI篇---TextView(文本框)
  9. Android(安卓)APN开发流程分析
  10. Akita 一套Android快速开发库 发布1.2版