Android中Activity的工作过程(一)

文章收藏的好句子:谁的人生没有苦难,但总有人能找到出路。

PS:本文是基于 Android Api 26 来分析源码的。

Activity 作为四大组件之一,它内部工作过程系统当然也是做了很多的封装,

这种封装使得启动一个 Activity 变得异常简单。在显式调用的情形下,假设我用 MainActivity 启动 Main2Activity,那么通过如下代码即可完成;

cefff840ad5ad8aa622eb3b217059a2d.png

为了更好的了解显示启动 Activity 时两个 Activity 的声明周期方法调用过程,我们先列出 MainActivity 和 Main2Activity 的代码;

(1)MainActivity 代码;

188cb30d9b3bc3c1d7b5364afa2b8fe1.png

(2)Main2Activity 代码;

a29eb486c598b9d09adef7014da92a1a.png

运行一下 app,日志打印如下所示;

8de6b9c8e2842d263276bf8aefa9d64b.png

看,跳转的过程中两个 Activity 的声明周期方法调用顺序是这样的:MainActivity.onPause -> Main2Activity.onCreate -> Main2Activity.onStart -> Main2Activity.onResume -> MainActivity.onStop。

由于上面提到的5个生命周期的流程涉及到的源码比较多,这里我们先找 MainActivity 的 onPause 方法流程走向

MainActivity 启动 Main2Activity 时,它内部是怎么做到的呢?我们看一下 Activity 的 startActivity(Intent intent) 方法的实现;

2035f99f1f3bf7a990d6be29aa69b7e1.png

startActivity(Intent intent) 方法调用了 Activity 的 startActivity(Intent intent, @Nullable Bundle options) 方法;

44bba940670655c4bc0829c5d2f9c830.png

由于 options 这个参数为空,所以执行的是注释2的代码块,我们看一下 Activity 的 startActivityForResult(@RequiresPermission Intent intent, int requestCode) 方法;

006677dc47fb89a53950b0857e57e97d.png

startActivityForResult(@RequiresPermission Intent intent, int reque-stCode) 方法调用了 Activity 的 startActivityForResult(@RequiresPermi-ssion Intent intent, int requestCode,@Nullable Bundle options) 方法;

bf2150c1c42bb6430351595aac8d40bf.png

看,为什么会执行注释3的代码?这里首先要判断 mParent == null 是否为 true,mParent 就是当前 Activity 的父 Activity,而我们的 Activity 是 MainActivity,它没有父类的 Activity,所以这里的 mParent == null 的结果是 true,实际上,mParent 常用在 ActivityGroup 中,而在API 14开始 ActivityGroup 已经废弃。

我们看一下注释4的代码,mInstrumentation 是 Instrumentation 类型的对象,我们看一下 Instrumentation 的 execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) 方法;

630abcf47e95cd7672361747c91c7e88.png

我们先看注释6的代码,看这个方法名,好像是检查启动 Activity 的结果,好吧,我们先进去看一下 Instrumentation 的 checkStartActivityResult(int res, Object intent) 方法;

121c00d7bc39c34ce1bcbd910d8f4d03.png

里面有很多各种检查的结果,我省略了很多;看注释7,如果我们没有在 AndroidManifest.xml 文件里面注册 Activity,那么就会抛出 Unable to find explicit activity class  have you declared this activity in your AndroidManifest.xml? 的异常。

好,我们现在回来看注释5的代码这里,ActivityManager.getService() 拿到的其实是 ActivityManagerService,所以我们往下看 ActivityManagerService 的 startActivity(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) 方法;

b52980c90fbbc1181565f4c0709d88f3.png

ActivityManagerService 的startActivity(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) 方法又调用了 ActivityManagerService 的 startActivityAsUser 方法;

1952758fc8af22ebd6a47ed3b87d1a9d.png

mActivityStarter 是一个ActivityStarter 实例对象,ActivityManagerService 的 startActivityAsUser(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) 方法调用了 ActivityStarter 的 startActivityMayWait(IApplicationThread caller, int callingUid,String callingPackage, Intent intent, String resolvedType,IVoiceInteractionSe-ssion voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode, int startFlags,ProfilerInfo profilerInfo, WaitResult outResult,Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,IActivityContainer iContainer, TaskRecord inTask, String reason) 方法;

final int startActivityMayWait(IApplicationThread caller, int callingUid,
                                   String callingPackage, Intent intent, String resolvedType,
                                   IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                                   IBinder resultTo, String resultWho, int requestCode, int startFlags,
                                   ProfilerInfo profilerInfo, WaitResult outResult,
                                   Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
                                   IActivityContainer iContainer, TaskRecord inTask, String reason) {
        ......
        synchronized (mService) {
            ......
            //9、
            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                    inTask, reason);
           ......
            return res;
        }
    }

看注释9的代码,又调用了 ActivityStarter 的 startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,IVoiceInteractionSession voiceSession, IVoi-ceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,String callingPackage, int realCallingPid, int realCallingUid, int startFlags,ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,Activity-Record[] outActivity, ActivityStackSupervisor.ActivityContainer contain-er,TaskRecord inTask, String reason) 方法;

733bf4bd17bb014e59222c8ed4aa019a.png

看注释10的代码,又调用了 ActivityStarter 的 startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceIn-teractor,IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,String callingPackage, int realCallingPid, int realCallingUid, int startFlags,ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,Ta-skRecord inTask) 方法;

10c87cfacd46ad8b553b839ca01e470c.png

看注释11,调用了 ActivityStarter 的 startActivity(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,ActivityRecord[] outActivity) 方法;

fd873faccda3f815f3792d4cf5d30d1a.png

看注释12,调用到了 ActivityStarter 的 startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,ActivityRec-ord[] outActivity) 方法;

// Note: This method should only be called from {@link startActivity}.
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                                       IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                                       int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                                       ActivityRecord[] outActivity) {
         ......
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                ......
            } else {
                ......
                //13、
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else {
            ......
        }
        ......
        return START_SUCCESS;
    }

看注释13的代码,因为我的 Main2Activity 的启动模式是 standard,所以会走这里,mSupervisor 是 ActivityStackSupervisor 类型的实例,我们看一下 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLock-ed(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) 方法;

50bc71c1b05838ed05fd14693e877add.png

看注释14,调用了 ActivityStack 的 resumeTopActivityUncheckedLo-cked(ActivityRecord prev, ActivityOptions options) 方法;

2bbcdae5253a8d78b999c6d6270c5f0e.png

看注释15,调用了 ActivityStack 的 resumeTopActivityInner-Locked(ActivityRecord prev, ActivityOptions options) 方法;

fae830d895e2ea63ab9d49770cde5a83.png

看注释16,调用了 ActivityStack 的 startPausingLocked(boolean userLeaving, boolean uiSleeping,ActivityRecord resuming, boolean pauseImmediately) 方法;

d7b9bc8e57065418e84b7a6d02cec7be.png

看注释17,prev.app.thread 是 ActivityThread 的内部类 ApplicatitonThread ,调用了 AppcationThread 的 schedulePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges, boolean dontReport) 方法;

a279786f03e3ea88d5b65b3dce9da708.png

看注释18,因为 finished 为 false,所有第一个参数是 H.PAUSE_ACTIVITY,又调用了 ActivityThread 的内部类 H;

da6949093cdd0db04524a346eb20f301.png

看注释19,又调用了 ActivityThread 的 handlePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges, boolean dontReport, int seq) 方法;

2976f0f3697ae4e0f57551be0c0ed1a0.png

看注释20,又调用了 ActivityThread 的 performPauseActivity(IBinder token, boolean finished,boolean saveState, String reason) 方法;

b2b07ff12efda0302b252e51ca9da2e2.png

看注释21,又调用了 ActivityThread 的 performPauseActivity(Activit-yClientRecord r, boolean finished,boolean saveState, String reason) 方法;

43babcd192b30370924665336da142c2.png

看注释22,又调用了 ActivityThread 的 performPauseActivity-IfNeeded(ActivityClientRecord r, String reason) 方法;

5c7d8fc6cf4b25e593f9c3022f633c06.png

看注释23,mInstrumentation 是 Instrumentation 类型的对象,所以调用了 Instrumentation 的 callActivityOnPause(Activity activity) 方法;

9868260f1039ca38d8034d11aea5fc34.png

看注释24,调用了 Activity 的 performPause 方法;

3a1772f88e33afcadc13679ccc8d3bcb.png

看到注释25了没有,Activity 的 onPause 方法已经找到,我们的目标已经完成,所以这篇文章到这里就写完了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值