客户端startActivity流程走向

  • 一个APP往往由许多的Activity组成,这些Activity之间肯定会发生界面跳转,这个时候我们就需要用startActivity这个方法,传递一些参数;或者使用startActivityForResult可以指定返回的requestCode。requestCode在当前Activity的onActivityResult方法中用来判断是不是我们跳转的Activity返回。

  • 这里需要注意的是,对于启动模式是SingleTask的Activity,执行startActivityForResult以后是直接返回,不会走到onActivityResult中。

  • 下面看一下它具体是怎么走的,core/java/android/app/Activity.java#startActivity

    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
     if (options != null) {
         startActivityForResult(intent, -1, options);
     } else {
         // Note we want to go through this call for compatibility with
         // applications that may have overridden the method.
         startActivityForResult(intent, -1);
     }
    

    }

  • 通过上述代码,我们不管调用的是startActivity还是startActivityForResult,最后都是走进startActivityForResult里面。

     public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
         @Nullable Bundle options) {
     if (mParent == null) {
         options = transferSpringboardActivityOptions(options);
         Instrumentation.ActivityResult ar =
             //具体执行启动Activity任务
             mInstrumentation.execStartActivity(
                 this, mMainThread.getApplicationThread(), mToken, this,
                 intent, requestCode, options);
          -----
          }
    }
    

    具体执行的就是execStartActivity这个方法,看一下实现:

    public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String target,
       Intent intent, int requestCode, Bundle options)

    看一下参数,who:当前界面句柄;contextThread:用来和AMS交互的,是我们在创建第一个Acitvity时候通过ActivityThread#performLaunchActivity中通过Activity.attach方法传进来的;intent:需要跳转的Activity信息:要跳转的Activity名称,传递的数据等;Bundle可选,要传递的数据也可以填写在这里。重点看一下这个方法里面的这句话:

	int result = ActivityManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);

    在这里我们走到了ActivityManagerService(AMS)中去执行:

    public final int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}

    看一下 startActivityAsUser实现:

    return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setResolvedType(resolvedType)
            .setResultTo(resultTo)
            .setResultWho(resultWho)
            .setRequestCode(requestCode)
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(bOptions)
            .setMayWait(userId)
            .execute();

services/core/java/com/android/am/ActivityStartController.java#obtainStarter的实现就一句话:

   ActivityStarter obtainStarter(Intent intent, String reason) {
       return mFactory.obtain().setIntent(intent).setReason(reason);
   }

    ActivityManagerService创建的时候,会做很多初始化动作,包括初始化ActivityStartController,在ActivityStartController的构造函数中直接调用ActivityStarter#DefaultFactory类,生成我们所需要的mFactory。最终通过obtain方法生成ActivityStarter句柄,并通过ActivityStarter#execute()执行。

   int execute() {
        try {
            // TODO(b/64750076): Look into passing request directly to these methods to allow
            // for transactional diffs and preprocessing.
            if (mRequest.mayWait) {
                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                ----
             }
         }
      }

    因为mRequest.mayWait为true,因此主要按照下面这个流程来实现:startActivityMayWait --> startActivity—>startActivityUnchecked,这个方法内容比较复杂,5.0以前是写在ActivityStackSupervisor.java中,5.0以后放在了ActivityStarter.java这个新文件中。
    讲到这里就不得不提一句配置在AndroidManifest.xml中的launchMode。举一个比较常见的场景就是A界面跳转到B界面。5.0以前会检查这个标志,如果A界面是SingleInstance或者B界面是SingleInstance或者SingleTask,跳转方式是startActivityForResult,则会立即执行onActivityResult,且返回结果为result_cancel。也就是说不会等到B界面返回,onActivityResult就已经执行;5.0以后则只会检查通过intent添加的flag,但不管是何种启动模式都是正常执行onActivityResult(也就是B界面返回以后再执行)。且根据flag标志,如果是singleTask,则检查该Activity是否存在实例,如果存在则从当前Activity往上清除至栈顶。否则就作为一个新界面跳转。详细描述可以参考:http://www.jianshu.com/p/2a9fcf3c11e4
    还是回到startActivityUnchecked这个方法,先简单描述一下主要实现功能:

	1.setInitialState:设置初始状态,计算出launchFlags.判断是否为需要返回结果(startActivityForResult启动),如果是且launchFlags为singleTask,则立即返回结果RESULT_CANCELED.具体在sendNewTaskResultRequestIfNeeded()方法中执行。和startActivity同样,销毁其上所有Activity.如果上一个界面也为singleTask,则调用onNewIntent.
	2.computeLaunchingTaskFlags:继续计算启动标志launchFlags。如果是singleInstance或者singletask,则检查指定的task是不是同一个,如果不是则抛出异常;否则就检查task是否为空,为空则直接添加;如果task不为空则显示在前台,不需要再新建task
	3.computeSourceStack:计算所需要的stack
	4.getReusableIntentActivity:获取复用的task不是activity,函数名称有歧义。
	5.如果可以复用,则清除其上的所有Activity至栈顶。调用TaskRecord.java中的performClearTaskForReuseLocked方法清除(如果找不到这个activity,则新建);
	6.检查是否为topActivity(这个activity存在),如果启动模式是singleTask或者singleInsance,则执行deliverNewIntent,发送onNewIntent给这个界面。
	7.setTargetStackAndMoveToFrontIfNeeded:如果在后台就需要显示在前台界面。
	8.mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,mOptions): 添加界面Window
	9.mSupervisor.resumeFocusedStackTopActivityLocked:启动Activity

  我们走进ActivityStackSupervisor.java#resumeFocusedStackTopActivityLocked看一下流程执行:

	1.targetStack.resumeTopActivityUncheckedLocked
	2.ActivityStack.java中:resumeTopActivityInnerLocked
	3.mStackSupervisor.startSpecificActivityLocked
	4.走进ActivityStackSupervisor.java#startSpecificActivityLocked,做两件事:
	(1)调用realStartActivityLocked,然后执行启动走onCreate和onResume; 
	(2)调用mService.startProcessLocked建立AMS通讯,最后调用Process.start-->zygoteProcess.start-->openZygoteSocketIfNeeded,通过ZygoteState.connect建立通讯,连接Zygote进程。

至此完成 Activity启动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值