Android源码分析:finish, startActivity

准备知识:
IdleHandler

它提供了一种机制,当主线程消息队列空闲时,会执行 IdleHandler 的回调方法。至于怎么算 “空闲”,我们可以看一下 MessageQueue.next() 方法。

Instrumentation

用于实现应用程序测试代码的基类。当在打开仪器的情况下运行时,这个类将在任何应用程序代码之前为您实例化,允许您监视系统与应用程序的所有交互。可以通过AndroidManifest.xml的标签描述该类的实现。

ActivityManager

该类提供与Activity、Service和Process相关的信息以及交互方法, 可以被看作是ActivityManagerService的辅助类。

ActivityManagerService

Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用程序的管理和调度等工作。

ActivityThread

管理应用程序进程中主线程的执行,根据Activity管理者的请求调度和执行activities、broadcasts及其相关的操作。

ActivityStack

负责单个Activity栈的状态和管理。

ActivityStackSupervisor

负责所有Activity栈的管理。内部管理了mHomeStack、mFocusedStack和mLastFocusedStack三个Activity栈。其中,mHomeStack管理的是Launcher相关的Activity栈;mFocusedStack管理的是当前显示在前台Activity的Activity栈;mLastFocusedStack管理的是上一次显示在前台Activity的Activity栈。

ClientLifecycleManager

用来管理多个客户端生命周期执行请求的管理类。

一. Activity.finish()

通过该分析解释onPause和onResume调用的及时,onStop,onDestroy可能会延期10s调用

1.1 执行onPause()和回调

  1. Activity.finish(DONT_FINISH_TASK_WITH_ACTIVITY);
    1. 搭载了带参数的 finish() 方法。参数是 DONT_FINISH_TASK_WITH_ACTIVITY ,含义也很直白,不会销毁 Activity 所在的任务栈。
    2. 其中activity中利用 Binder 调用了 AMS.finishActivity() 方法
  2. ActivityManagerService.finishActivity(IBinder token, int resultCode, Intent resultData,int finishTask)
    1. ActivityStack.requestFinishActivityLocked()
  3. ActivityStack.requestFinishActivityLocked()
  4. ActivityStack.finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,String reason, boolean oomAdj, boolean pauseImmediately)
    1. r.makeFinishingLocked();// 前面会做重复 finish 的检测就是依赖这个值
    2. startPausingLocked(false, false, null, pauseImmediately);// 开始 pause mResumedActivity
  5. ActivityStack.startPausingLocked(boolean userLeaving, boolean uiSleeping,ActivityRecord resuming, boolean pauseImmediately)
    1. 第一步通过 ClientLifecycleManager 分发生命周期流程。
    2. 第二步是发送一个延时 500ms 的消息,等待一下 onPause 流程.但是如果第一步中在 500ms 内已经完成了流程,则会取消这个消息。所以这两步的最终逻辑其实是一致的。这里就直接看第一步。
  6. ClientLifecycleManager它会向主线程的 Handler H 发送 EXECUTE_TRANSACTION 事件,调用 XXXActivityItem 的 execute() 和 postExecute() 方法。execute() 方法中会 Binder 调用 ActivityThread 中对应的 handleXXXActivity() 方法。在这里就是 handlePauseActivity() 方法,其中会通过 Instrumentation.callActivityOnPause(r.activity) 方法回调 Activity.onPause() 。
  7. Instrumentation.callActivityOnPause(Activity activity)
    1. activity.performPause();Activity onPause()被执行。
    2. onPause() 方法就被执行了。但是流程没有结束,接着就该显示下一个 Activity 了。

小结:调用finish会立即执行当前Activity的onPause和下一个Activity的显示流程

1.2 执行finish()流程

  1. 前面刚刚说过会调用 PauseActivityItem 的 execute() 和 postExecute() 方法。execute() 方法回调了当前 Activity.onPause(),而 postExecute() 方法就是去寻找要显示的 Activity 。
  2. PauseActivityItem.postExecute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions)
    1. ActivityManager.getService().activityPaused(token);
  3. ActivityManagerService.activityPaused(IBinder token)
  4. ActivityStack.activityPausedLocked()
    1. mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r) ,移除的就是之前延迟 500ms 的消息。接着看 completePauseLocked() 方法。
  5. ActivityStack.ompletePauseLocked(boolean resumeNext, ActivityRecord resuming)
    1. 判断了 finishing 状态,还记得 finishing 在何处被赋值为 true 的吗?在 Activity.finish() -> AMS.finishActivity() -> ActivitySta
    2. ck.requestFinishActivityLocked() -> ActivityStack.finishActivityLocked() 方法中。所以接着调用的是 finishCurrentActivityLocked() 方法
    3. // 当前获取焦点的 mStackSupervisor.getFocusedStack(); // 恢复要显示的 activity mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null); 此时会标记10s的超时
  6. ActivityStack.finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj,String reason)
    1. mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)&& next != null && !next.nowVisible addToStopping
    2. mode == FINISH_IMMEDIATELY || (prevState == PAUSED && (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))|| finishingActivityInNonFocusedStack|| prevState == STOPPING|| prevState == STOPPED|| prevState == ActivityState.INITIALIZING
  7. ActivityStack.addToStopping
    1. 这些在等待销毁的 Activity 被保存在了 ActivityStackSupervisor 的 mStoppingActivities 集合中,它是一个 ArrayList 。
    2. 整个 finish 流程就到此为止了。前一个 Activity 被保存在了 ActivityStackSupervisor.mStoppingActivities 集合中,新的 Activity 被显示出来了。

小结:finish流程执行完成只是将该Activity放入待销毁的ArrayList 中

1.3 真正回调onStop,onDestroy

  1. ActivityThread.handleResumeActivity()
    1. handleResumeActivity() 方法是整个 UI 显示流程的重中之重,它首先会回调 Activity.onResume() , 然后将 DecorView 添加到 Window 上,其中又包括了创建 ViewRootImpl,创建 Choreographer,与 WMS 进行 Binder 通信,注册 vsync 信号,著名的 measure/draw/layout
    2. 完成最终的界面绘制和显示之后Looper.myQueue().addIdleHandler(new Idler())
  2. MessageQueue.next()
    1. 当新的 Activity 完成页面绘制并显示之后,主线程就可以停下歇一歇,来执行 IdleHandler 了。再回来 handleResumeActivity() 中来
  3. ActivityThread.handleResumeActivity()
    1. Idler implements MessageQueue.IdleHandler
      1. Idler. queueIdle()
        1. 调用 AMS.activityIdle()
  4. ActivityManagerService.activityIdle(IBinder token, Configuration config, boolean stopProfiling)
  5. ActivityStackSupervisor.activityIdleInternalLocked()
    1. stops 和 finishes 分别是要 stop 和 destroy 的两个 ActivityRecord 数组。stops 数组是通过 ActivityStackSuperVisor.processStoppingActivitiesLocked() 方法获取的
  6. ActivityStackSupervisor.processStoppingActivitiesLocked(ActivityRecord idleActivity, boolean remove, boolean processPausingActivities)
    1. 遍历的是ActivityStackSuperVisor 中的 mStoppingActivities 集合 。在前面分析 finish() 流程到最后的 addToStopping() 方法时提到过,

小结:MessageQueue.next() 中主线程完成后执行IdleHandler,去执行ArrayList中待销毁的Activity

1.4 为什么10s onStop/onDestroy:

  1. ActivityStackSuperVisor.resumeFocusedStackTopActivityLocked()
  2. ActivityStack.resumeTopActivityUncheckedLocked()
  3. ActivityStack.resumeTopActivityInnerLocked()
  4. ActivityRecord.completeResumeLocked()
  5. ActivityStackSuperVisor.scheduleIdleTimeoutLocked()
    1. IDLE_TIMEOUT 的值是 10
  6. ActivityStackSupervisorHandler. activityIdleInternalLocked()处理的如果 10s 内主线程执行了 Idler 的话,就会移除这个消息

小结:执行finish流程中 当前获取焦点的恢复要显示的 activity 会标记10s的超时,如果10s没执行Idler就会强制执行。

参考

  1. 为什么 Activity.finish() 之后 10s 才 onDestroy ?
  2. ActivityManagerService 你了解多少?
  3. (Android 9.0)Activity启动流程源码分析
  4. IdleHandler 的原理分析和妙用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值