网站建设虚线代码,wordpress主题企业,南京华佑千家装饰工程有限公司,南昌seo全网营销忽然有一天#xff0c;我想要做一件事#xff1a;去代码中去验证那些曾经被“灌输”的理论。 – 服装… 忽然有一天我想要做一件事去代码中去验证那些曾经被“灌输”的理论。 – 服装学院的IT男 本篇已收录于Activity短暂的一生系列 欢迎一起学习讨论Android应用开发或者WMS VWJB6995 Q707409815 正文
Activity 生命周期是学习 Android 必定要掌握的知识点但是刚入行的同学对于这个概念基本上是靠死记硬背有一些实际工作经验的同学在工作中通过实现业务需求或者解决一些BUG基本上是可以知道哪些生命周期对应用户操作的哪一步。
虽然触发生命周期的场景很多当前只还是以在桌面启动应用来分析但是完整的跟过这一流程的代码逻辑就能加深对生命周期本质的理解其他场景的生命周期切换也不是啥问题。
生命周期系列 Activity生命周期之onPause onCreate,onStart,onResume-1 onCreate,onStart,onResume-2 Activity生命周期之onStop-1 Activity生命周期之onStop-2 Activity生命周期之onDestory
本篇会介绍生命周期的执行顺序和 onPause 的执行逻辑
1. 生命周期介绍
回忆一下2个 Activity 的定义 SourceActivity执行 startActivity 方法的 Activity也就是发起请求的Activity当前就是 Launcher 的 Activity TargetActivity需要被启动的 Activity当前就是“电话”应用在清单文件配置的 MainActivity
在 Activity.java 中每个生个周期的执行都有对应的log打印比如 onPause
# Activity// 默认为false需要收到打开private static final boolean DEBUG_LIFECYCLE true;protected void onPause() {if (DEBUG_LIFECYCLE) Slog.v(TAG, onPause this);......}打开log开关后操作一遍就获得到了下面的生命周期日志 根据这里的日志打印就可以得出以下结论 先执行 SourceActivity 的 onPause 然后依次执行 TargetActivity onCreate,onStart,onResume 三个生命周期 最后执行 SourceActivity 的 onStop 冷启动热启动的生命周期执行顺序都是一样的 如果没有条件编译AOSP的同学搞个Activity在各自的生命周期加上log也能得到这样的一份log 根据之前【Activity启动流程】的知识和这份生命周期的log可以得到下面这个图 SystemService 会先触发 SourceActivity 的 onPause然后才允许启动新的 TargetActivity 。鲁迅曾说过俗话说旧的不去新的不来
SourceActivity 执行了 onPause 的时候TargetActivity 还没起来所以说 onPause 的时候Activity也是可见的只有知道到 onStop才不可见因为 TargetActivity 已经显示了。
知道这几个生命周期的执行顺序其实就已经可以开始反向推到调用流程了但是可以通过 events 日志把流程具体化完整流程对应的 events 日志如下 只有分析流程的时候按顺序像连线一样找到各个日志打印的地方形成调用链那整个生命周期的源码分析就完成了。
这里把 events 日志做了一些简化和加上了注释如果以后遇到流程异常的就可以和这份正常的日志对比一下哪一步开始出问题了然后去定位问题原因。
// SystemService端创建TargetActivity writeWmCreateActivity
03-27 14:41:06.428 27889 28629 I wm_create_activity: [0,253598020,21,com.google.android.dialer/.extensions.GoogleDialtactsActivity,android.intent.action.MAIN,NULL,NULL,270532608]// SystemService端触发SourceActivity的Pause writeWmPauseActivity
03-27 14:41:06.431 27889 28629 I wm_pause_activity: [0,51114540,com.android.launcher3/.uioverrides.QuickstepLauncher,userLeavingtrue,pauseBackTasks]// SourceActivity应用端将执行onPause writeWmOnPausedCalled
03-27 14:41:06.448 28606 28606 I wm_on_paused_called: [51114540,com.android.launcher3.uioverrides.QuickstepLauncher,performPause]// SystemService端把SourceActivity添加进需要stop的集合 writeWmAddToStopping
03-27 14:41:06.459 27889 28630 I wm_add_to_stopping: [0,51114540,com.android.launcher3/.uioverrides.QuickstepLauncher,makeInvisible]// SystemService端要真正触发TargetActivity启动 writeWmRestartActivity
03-27 14:41:06.487 27889 28630 I wm_restart_activity: [0,253598020,21,com.google.android.dialer/.extensions.GoogleDialtactsActivity]// TargetActivity端将执行onCreate (writeWmOnCreateCalled)
03-27 14:41:06.769 3401 3401 I wm_on_create_called: [253598020,com.google.android.dialer.extensions.GoogleDialtactsActivity,performCreate]// TargetActivity端将执行onStart (writeWmOnStartCalled)
03-27 14:41:06.900 3401 3401 I wm_on_start_called: [253598020,com.google.android.dialer.extensions.GoogleDialtactsActivity,handleStartActivity]// TargetActivity端将执行Resume (writeWmOnResumeCalled)
03-27 14:41:06.911 3401 3401 I wm_on_resume_called: [253598020,com.google.android.dialer.extensions.GoogleDialtactsActivity,RESUME_ACTIVITY]// SystemService端触发SourceActivity的stop writeWmStopActivity
03-27 14:41:07.097 27889 30491 I wm_stop_activity: [0,51114540,com.android.launcher3/.uioverrides.QuickstepLauncher]// SourceActivity应用端将执行onStop (writeWmStopActivity)
03-27 14:41:07.119 28606 28606 I wm_on_stop_called: [51114540,com.android.launcher3.uioverrides.QuickstepLauncher,STOP_ACTIVITY_ITEM]1.1 生命周期事务
Activity各个生命周期的执行被封装成了一个事务具体的映射关系如下
LaunchActivityItem onCreate
StartActivityItem Start
ResumeActivityItem onResume
PauseActivityItem Pause
StopActivityItem Stop
ActivityRelaunchItem relaunch
ActivityResultItem result各个类被定义在 frameworks/base/core/java/android/app/servertransaction/ 路径下 这些类都实现了 BaseClientRequest 接口所以都有 preExecute execute postExecute 3个方法。 其实 execute 表示真正触发应用端执行对应的生命周期而 preExecutepostExecute 分别对应执行生命周期前后该做的事这3个方法的执行循序如下
preExecute -》execute -》postExecute这些后续在代码中也能论证。
2. onPause
根据之前的分析知道 SourceActivity 是最先执行的这个时候 TargetActivity 是还没有启动的。
pause流程对应的事务是 PauseActivityItem 所以构建这个事务之前的调用逻辑就是 pause 流程在 SystemService 的处理而 PauseActivityItem::execute 后的调用逻辑就是 pause 流程在应用端的处理。
目标明确开始分析看代码。
2.1 SystemService 触发 pause 流程
构建 PauseActivityItem 的地方在 TaskFragment::schedulePauseActivity 方法中,在【Activity启动流程1】中知道在流程早起会执行下面这段调用链 ActivityTaskManagerService::startActivityActivityTaskManagerService::startActivityAsUserActivityTaskManagerService::startActivityAsUserActivityStartController::obtainStarterActivityStarter::executeActivityStarter::executeRequest -- 构建 ActivityRecord --2.1 创建ActivityRecordActivityStarter::startActivityUncheckedActivityStarter::startActivityInner -- 2.2 关键函数startActivityInnerActivityStarter::getOrCreateRootTask -- 2.2.1 创建或者拿到TaskActivityStarter::setNewTask -- 2.2.2 将task与activityRecord 绑定RootWindowContainer::resumeFocusedTasksTopActivities --2.2.3 处理需要显示的ActivityRootWindowContainer::resumeFocusedTasksTopActivities 方法后续的逻辑如下 RootWindowContainer::resumeFocusedTasksTopActivitiesTask::resumeTopActivityUncheckedLockedTask::resumeTopActivityInnerLockedTaskFragment::resumeTopActivity TaskDisplayArea::pauseBackTasks -- Pause SourceActivity 逻辑 第一次执行WindowContainer::forAllLeafTaskTaskFragment::forAllLeafTaskFragmentsTaskFragment::startPausingTaskFragment::startPausingTaskFragment::schedulePauseActivity --构建 PauseActivityItem这里是触发SourceActivity的pauseActivityTaskManagerService::startProcessAsync -- 创建TargetActivity所在的进程 第一次执行且需要启动目标进程ActivityTaskSupervisor::startSpecificActivity -- 启动TargetActivity第二次执行现在有个印象需要注意的是上面的 RootWindowContainer::resumeFocusedTasksTopActivities 触发的逻辑是会执行2次的 第一次调用就是启动流程 startActivity 触发的执行到 TaskFragment::resumeTopActivity 方法时触发 SourceActivity 的 pause 流程和创建 TargetActivity 的进程。应用内启动Activity肯定就不会触发进程创建了
第二次触发是 SourceActivity 执行完 pause 后就会触发 completePause 流程这次执行到 TaskFragment::resumeTopActivity 方法时走的是触发启动 TargetActivity 流程。完整调用链如下 ActivityClientController::activityPausedActivityRecord::activityPausedTaskFragment::completePauseRootWindowContainer::resumeFocusedTasksTopActivities --分支1 再次执行 resumeFocusedTasksTopActivitiesRootWindowContainer::resumeFocusedTasksTopActivitiesTask::resumeTopActivityUncheckedLockedTask::resumeTopActivityInnerLockedTaskFragment::resumeTopActivityActivityTaskSupervisor::startSpecificActivity -- 启动TargetActivityRootWindowContainer::ensureActivitiesVisible --分支2 确保有Activity显示流程这里需要注意 completePause 流程再次执行 RootWindowContainer::resumeFocusedTasksTopActivities 方法时内部还会触发 TaskFragment::resumeTopActivity 方法而这一次触发的是启动 TargetActivity 的流程。
同一个方法因为执行时机不同走不同的逻辑这种情况在分析源码的时候非常让人头疼上面做了一些说明并且提供了调用链。
本篇其实需要注意的只有第一次执行的逻辑处理因为第二次是 completePause 流程了触发的是TargetActivity 流程也就是 TargetActivity 的onCreate,onStart,onResume 三个生命周期执行是下一篇的触发逻辑当前有个印象即可。
其他的地方在【Activity启动流程】系列都分析过来目前只关注 pause 逻辑即可看一下 TaskFragment::resumeTopActivity 方法的代码。
2.1.1 TaskFragment::resumeTopActivity 方法 # TaskFragmentfinal boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,boolean deferPause) {// 这里的next返回下一个需要显示的ActivityActivityRecord next topRunningActivity(true /* focusableOnly */);...... // 如果跳过的这些逻辑都没执行return则开始执行resume流程如果被return了也会打印日志。 // 打印日志需要显示哪个Activity也就是SourceActivityif (DEBUG_SWITCH) Slog.v(TAG_SWITCH, Resuming next);......// 重点* 1. 第一次执行走这执行SourceActivity的pause流程boolean pausing !deferPause taskDisplayArea.pauseBackTasks(next);......if (pausing) {ProtoLog.v(WM_DEBUG_STATES, resumeTopActivity: Skip resume: need to start pausing);if (next.attachedToProcess()) {......} else if (!next.isProcessRunning()) {// 进程没有运行则触发异步创建进程。 当前逻辑肯定是执行final boolean isTop this taskDisplayArea.getFocusedRootTask();mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY: HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);}......// 注意这里会return所以第一次执行到这就结束了。return true;}......ProtoLog.d(WM_DEBUG_STATES, resumeTopActivity: Restarting %s, next);// 重点*2. 第二次执行的时候走这SourceActivity已经执行完pause流程了所以走这启动Activity走这mTaskSupervisor.startSpecificActivity(next, true, true); }这个方法是极其复杂的 但是基于前面的铺垫后再看这个方法我觉得应该目标明确了由于当前是分析的是 onPause流程所以只看第一次执行的调用链即可也就是 pauseBackTasks 方法。
TaskDisplayArea::pauseBackTasks 方法的逻辑从前面的调用链知道会执行 TaskFragment::schedulePauseActivity 方法这中间的调用逻辑在【Activity启动流程-2】中有详细分析当前直接看 schedulePauseActivity 方法。
# TaskFragmentvoid schedulePauseActivity(ActivityRecord prev, boolean userLeaving,boolean pauseImmediately, String reason) {// Proto日志ProtoLog.v(WM_DEBUG_STATES, Enqueueing pending pause: %s, prev);try {// 输出events 日志 wm_pause_activityEventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),prev.shortComponentName, userLeaving userLeaving, reason);// 重点* 构建并执行PauseActivityItemmAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),prev.token, PauseActivityItem.obtain(prev.finishing, userLeaving,prev.configChangeFlags, pauseImmediately));} catch (Exception e) {......}}打印第一个 events 日志wm_pause_activity 构建执行 PauseActivityItem 事务
SystemService 触发 pause 的逻辑就分析完了PauseActivityItem 是承上启下的关键线索看看这个事务做了些什么。
2.2 PauseActivityItem # PauseActivityItemOverridepublic void execute(ClientTransactionHandler client, ActivityClientRecord r,PendingTransactionActions pendingActions) {// traceTrace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, activityPause);// 触发应用进程pauseclient.handlePauseActivity(r, mFinished, mUserLeaving, mConfigChanges, pendingActions,PAUSE_ACTIVITY_ITEM);Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);}Overridepublic int getTargetState() {return ON_PAUSE;}Overridepublic void postExecute(ClientTransactionHandler client, IBinder token,PendingTransactionActions pendingActions) {if (mDontReport) {return;}// 自己加的TraceTrace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, activityPaused);// TODO(lifecycler): Use interface callback instead of actual implementation.// 触发 completePause 流程ActivityClient.getInstance().activityPaused(token);Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);}先执行 execute 最终触发应用端 Activity 的 onPause 然后执行 postExecute 这里的逻辑是由 SystemService 执行 completePause 流程
这2个发生是同步触发但是具体触发逻辑所在的进程都不一样所以肯定是异步执行的没有强绑定关系 换句话说就是 应用端的 Activity 是不是真的顺利执行完了 onPause和 completePause 流程没有必然关系。
这点很重要后面看 onStop 流程的时候还会提到。
activityPaused 触发的后续逻辑就是 2.1 小节提到的第二次执行 TaskFragment::resumeTopActivity 方法来启动 Activity 的触发点。
当然本篇还是看 pause 逻辑所以直接看 execute 方法触发的应用端是如何处理的。
2.3 应用端执行pause
应用端调用链如下
ActivityThread::handlePauseActivityActivityThread::performPauseActivityActivityThread::performPauseActivityIfNeededInstrumentationcallActivityOnPauseActivity::performPauseActivity::onPause -- onPauseActivityClientRecord::setState -- 设置状态ON_PAUSE4
代码流程也很简单看一下。 # ActivityThreadOverridepublic void handlePauseActivity(ActivityClientRecord r, boolean finished, boolean userLeaving,int configChanges, PendingTransactionActions pendingActions, String reason) {......r.activity.mConfigChangeFlags | configChanges;performPauseActivity(r, finished, reason, pendingActions);......}private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,PendingTransactionActions pendingActions) {......// Pre-Honeycomb apps always save their state before pausingfinal boolean shouldSaveState !r.activity.mFinished r.isPreHoneycomb();if (shouldSaveState) {// 安卓3之前的版本是在onPause执行执行OnSaveInstanceState的callActivityOnSaveInstanceState(r);}// onPause 逻辑performPauseActivityIfNeeded(r, reason);......}稍微提到了一下 OnSaveInstanceState 的调用时机Honeycomb 是安卓3 现在基本上没有这种手机了了解一下即可继续看主流程。 # ActivityThreadInstrumentation mInstrumentation;private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {// 如果已经 paused 就不许要处理了if (r.paused) {// You are already paused silly...return;}try {r.activity.mCalled false;// 主流程mInstrumentation.callActivityOnPause(r.activity);if (!r.activity.mCalled) {throw new SuperNotCalledException(Activity safeToComponentShortString(r.intent) did not call through to super.onPause());}} catch ......// 需要留意一下 这里的状态是生命周期不是ActivityRecord的那个状态 r.setState(ON_PAUSE);}又看到了 Instrumentation # Instrumentationpublic void callActivityOnPause(Activity activity) {activity.performPause();}!----# Activity final void performPause() {// 1. Trace beginif (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, performPause: mComponent.getClassName());}dispatchActivityPrePaused();mDoReportFullyDrawn false;// 2. Fragments处理mFragments.dispatchPause();mCalled false;// 3. 重点* onPauseonPause();// 4. events日志 wm_on_paused_calledEventLogTags.writeWmOnPausedCalled(mIdent, getComponentName().getClassName(),performPause);mResumed false;......// Trace endTrace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);}到这里 onPause 流程就分析完了 这里有几个需要注意的点 有Trace 对Fragments处理 最重要的触发了 Activity 的 onPause 打印日志 wm_on_paused_called 表示应用端已经pause了
到这里 SourceActivity 的 Pause 流程已经完全结束了。
3 ActivityClientRecord 是什么
在 ActivityThread::performPauseActivityIfNeeded 中看到在触发 onPause 执行后还会调用 ActivityClientRecord::setState 方法传递了一个 ON_PAUSE 进去。
这句代码大概意思猜着就是设置一个 ON_PAUSE 的状态保存起来。
可是 SystemService 端有个 ActivityRecord 来记录 Activity的一些信息那这个 ActivityClientRecord 又是什么呢
从命名上来看好像和 ActivityRecord 类似是 Client客户端这边记录 Activity 的一个类实际上也确实如此ActivityClientRecord 内部也保存了很多与 Activity 启动和运行相关的各种参数如Intent、token、binder引用等。以后遇到再说不过目前我们关注生命周期相关的先看看 setState 这个方法。
# ActivityThread$ActivityClientRecord// 是否pausedUnsupportedAppUsageboolean paused;// 是否stopedUnsupportedAppUsageboolean stopped;// 生命周期状态LifecycleStateprivate int mLifecycleState PRE_ON_CREATE;/** Update the current lifecycle state for internal bookkeeping. */// 更新内部保存的生命周期状态public void setState(LifecycleState int newLifecycleState) {mLifecycleState newLifecycleState;switch (mLifecycleState) {case ON_CREATE:// 刚刚创建不可见不可交互paused true; stopped true; break;case ON_START:// 还没完全进入前台但已经可见不可交互paused true; stopped false; break;case ON_RESUME:// 可见可交互paused false;stopped false; break;case ON_PAUSE:// 未被完全遮挡可见不可交互paused true; stopped false; break;case ON_STOP:// 被完全遮挡所以不可见也不可交互paused true; stopped true; break;}}这段代码有3个变量: paused 表示当前Activity 是否处于暂停pause状态也就是能不能和用户交互 stopped 表示当前Activity是否处于 停止stop状态也就是能不能被用户可见 mLifecycleState 这是一个被LifecycleState注解的变量说明取值只能是内部定义的几个生命周期 关于pause和stop的区别可能有些小伙伴还很迷糊这里表达一下我的理解 onPause和onStop都是不能和用户交互的但是 onPause 的时候Activity 还是可见的比如出现一个dialog主题的Activity这个时候下面的 Activity 就是pause但不是stop因为它还能被用户看见。 从log来看SourceActivity 的onPause是最先执行的但是onStop却要等 TargetActivity 执行完 onResume 再执行 抛开代码从实际情况来说SourceActivity 要不可见就只有等 TargetActivity 完全显示onResume的时候才可以算 onStop 了 LifecycleState 注解是定义在 ActivityLifecycleItem下的 # ActivityLifecycleItemRetention(RetentionPolicy.SOURCE)public interface LifecycleState{}public static final int UNDEFINED -1;public static final int PRE_ON_CREATE 0;public static final int ON_CREATE 1;public static final int ON_START 2;public static final int ON_RESUME 3;public static final int ON_PAUSE 4;public static final int ON_STOP 5;public static final int ON_DESTROY 6;public static final int ON_RESTART 7;可以看到 从 1-7 刚好是和 7个生命周期对应的这里需要注意对应的几个int值后面的代码还要用到。
当前 pause 流程传递了一个 ON_PAUSE 进去 那当前 mLifecycleState 的值就是 ON_PAUSE4。
4. 总结
本篇首先明确了启动 Activity 生命周期的先后执行顺序然后介绍了完整流程的 events 日志。
然后知道了 startActivity 流程最开始会执行到 TaskFragment::resumeTopActivity 方法在这里会触发 SourceActivity 的 pause 流程同时还会创建 TargetActivity 所在的进程有必要的话 我对关键方法加上了一个 Trace 后当前桌面冷启动应用场景得到的Trace如下 可以看到 TaskFragment::resumeTopActivity 执行了2次上图是第一次 执行进程在 system_service 执行了 pauseBackTasks 流程也就是 SourceActivity 的 pause 触发了TargetActivity 所在的进程创建
pauseBackTasks 方法后面会执行 TaskFragment::schedulePauseActivity 方法在这个方法中有2个点 打印日志wm_pause_activity 构建执行 PauseActivityItem
而 PauseActivityItem 也做了2件事: 先执行 execute 最终触发应用端 Activity 的 onPause 然后执行 postExecute 这里的逻辑是由 SystemService 执行 completePause 流程。
本篇关心的是 execute 方法除非的逻辑在应用段执行到 onPause 的逻辑打印了 wm_on_paused_called 日志流程也就分析完了。
最后再补充一下 postExecute 方法触 执行进程还是在 system_service 这里的 resumeTopActivity 上面是 activityPaused也就是我在 PauseActivityItem::postExecute 加是 trace 虽然还会执行 pauseBackTasks 但是下面没有构建 pause 事务的逻辑了 这一次执行还会触发prepareAppTransition方法 最终要的是要创建 TargetActivity 了下一篇是基于这个基础