前言

在前文中已经讲到.

  1. Launcher拉起新的Activity,并在ATMS中执行pause Activity的操作,以及当前Activity执行Pause的流程.
  2. 在当前Activity执行pause时同步执行拉起新进程操作.

本文主要讲当前Activity已经执行完Pause操作,调用ATMS的activityPaused接口,告知当前Activity已经暂停成功了的流程.

详细流程分析

PauseActivityItem执行postExecute时,就会调用ActivityTaskManager.getService().activityPaused(token);这个方法通过binder调用到ATMS的activityPaused.

activityPaused:1843, ActivityTaskManagerService

    public final void activityPaused(IBinder token) {
synchronized (mGlobalLock) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused");
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r != null) {
r.activityPaused(false);
}
}
Binder.restoreCallingIdentity(origId);
}

这里首先通过token去获取了当前Pause的Activity在ATMS中对应的ActivityRecord实例,然后调用

ActivityRecord的activityPaused.

todo:Activity,ActivityRecord,token,stack,task之间的关系.

activityPaused:4930, ActivityRecord

void activityPaused(boolean timeout) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
"Activity paused: token=" + appToken + ", timeout=" + timeout); final ActivityStack stack = getStack();

首先查找当前的ActivityRecord对应的ActivityStack

        if (stack != null) {
removePauseTimeout(); if (stack.mPausingActivity == this) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + this
+ (timeout ? " (due to timeout)" : " (pause complete)"));
mAtmService.deferWindowLayout();
try {
stack.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
} finally {
mAtmService.continueWindowLayout();
}
return;

如果stack正在pausing的Activity是当前Activity,那么调用stack.completePauseLocked去resume下一个待resume的activity.

            } else {
if (isState(PAUSING)) {
setState(PAUSED, "activityPausedLocked");
if (finishing) {
if (DEBUG_PAUSE) Slog.v(TAG,
"Executing finish of failed to pause activity: " + this);
completeFinishing("activityPausedLocked");
}
}
}

如果当前在pausing的activity不是当前的这个Activity.那么做一些状态的处理.(假设Activity a pause但是超时了,那么在超时的时候就会调用paused操作.此时又把当前resume的Activity pause,而 a Activity有回调了activityPaused接口就会进入这个分支.)

        }

        mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}

如果当前Activity的堆栈为空,或者当前pausing Activity不是当前这个Activity,那么还要调用mRootWindowContainerensureActivitiesVisible.

这里pausing Activity就是当前这个Activity,所以执行stack.completePauseLocked

completePauseLocked:1166, ActivityStack

void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
ActivityRecord prev = mPausingActivity;
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev); if (prev != null) {
prev.setWillCloseOrEnterPip(false);
final boolean wasStopping = prev.isState(STOPPING);
prev.setState(PAUSED, "completePausedLocked");
if (prev.finishing) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
prev = prev.completeFinishing("completePausedLocked");
} else if (prev.hasProcess()) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
+ " wasStopping=" + wasStopping
+ " visibleRequested=" + prev.mVisibleRequested);
if (prev.deferRelaunchUntilPaused) {
// Complete the deferred relaunch that was waiting for pause to complete.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
prev.relaunchActivityLocked(prev.preserveWindowOnDeferredRelaunch);
} else if (wasStopping) {
// We are also stopping, the stop request must have gone soon after the pause.
// We can't clobber it, because the stop confirmation will not be handled.
// We don't need to schedule another stop, we only need to let it happen.
prev.setState(STOPPING, "completePausedLocked");
} else if (!prev.mVisibleRequested || shouldSleepOrShutDownActivities()) {
// Clear out any deferred client hide we might currently have.
prev.setDeferHidingClient(false);
// If we were visible then resumeTopActivities will release resources before
// stopping.
prev.addToStopping(true /* scheduleIdle */, false /* idleDelayed */,
"completePauseLocked");
}
} else {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);
prev = null;
}
// It is possible the activity was freezing the screen before it was paused.
// In that case go ahead and remove the freeze this activity has on the screen
// since it is no longer visible.
if (prev != null) {
prev.stopFreezingScreenLocked(true /*force*/);
}
mPausingActivity = null;
}

先获取当前Activity栈中待pause的Activity,执行一些Activity pause后的收尾工作.

        if (resumeNext) {
final ActivityStack topStack = mRootWindowContainer.getTopDisplayFocusedStack();
if (topStack != null && !topStack.shouldSleepOrShutDownActivities()) {
mRootWindowContainer.resumeFocusedStacksTopActivities(topStack, prev, null);
} else {
checkReadyForSleep();
final ActivityRecord top = topStack != null ? topStack.topRunningActivity() : null;
if (top == null || (prev != null && top != prev)) {
// If there are no more activities available to run, do resume anyway to start
// something. Also if the top activity on the stack is not the just paused
// activity, we need to go ahead and resume it to ensure we complete an
// in-flight app switch.
mRootWindowContainer.resumeFocusedStacksTopActivities();
}
}
}

如果需要resume 下一个activity,那么调用mRootWindowContainer.resumeFocusedStacksTopActivities去resume它.

上面两个不同参数的resumeFocusedStacksTopActivities方法的区别在于第一种是确定要拉起哪个堆栈中的Activity,另一个是要从所有的显示区域去找一个需要显示的堆栈,如果找不到的话则拉起Launcher.

当前Activity的onPause执行完后,调用Paused接口的更多相关文章

  1. 用一个bat文件调用另外两个bat文件,当1.bat执行完后再执行2.bat

    用一个bat文件调用另外两个bat文件,当1.bat执行完后再执行2.bat 摘自:https://zhidao.baidu.com/question/492732911.html @echo off ...

  2. 在Struts.xml中的result元素指的是:指定动作类的动作方法执行完后的结果视图.

    result结果集 上一篇文章主要讲Struts2框架(4)---Action类访问servlet这篇主要讲result结果集 在Struts.xml中的result元素指的是:指定动作类的动作方法执 ...

  3. vue在一个方法执行完后再执行另一个方法

    vue在一个方法执行完后执行另一个方法 用Promise来实现.Promise是ES6的新特性,用于处理异步操作逻辑,用过给Promise添加then和catch函数,处理成功和失败的情况 ES7中新 ...

  4. 有三个线程,a、b、c,a打印“T1”,b打印“T2”,c打印“T3”,a执行完后,b执行;b执行完后,c执行。如此循环100遍

    有三个线程,a.b.c,a打印“T1”,b打印“T2”,c打印“T3”,a执行完后,b执行:b执行完后,c执行.如此循环100遍. package com.company; /** * 测试三个线程协 ...

  5. T100——作业action执行其他P作业,后台背景执行完后才能继续操作改作业

    范例:如axmt500订单,查询开单占用量: 客制作业cxmp500,通过参数-订单号,查询该订单下的料件,目前有库存量.开单占用量.库存可用量,查询后更新到该订单下的单身对应栏位: 现在axmt50 ...

  6. iOS AFNetWorking中block执行完后再执行其它操作

    需求:同时进行两次网络请求,网络请求是异步的,在网络请求成功后进行其它的操作.两个网络请求是这样,一个网络请求中block执行完之后,再进行其它操作,也是一样的原理,只是这时候不需要线程组了,只需要信 ...

  7. 现在有T1、T2、T3三个线程,怎样保证T2在T1执行完后执行,T3在T2执行完后执行?使用Join

    public class TestJoin { public static void main(String[] args) { Thread t1 = new Thread(new T1(), &q ...

  8. C#子线程执行完后,调用主线程的方法

    private delegate void CheckVersionNumber_CallBack(string str);//定义一个为委托 用于 检测版本 //检测版本private void m ...

  9. 对象内存空间 在创建对象后 运行时 会把对象的方法放到jvm的方法区中 调用时 将方法拿到栈中 执行完后 这个方法会出栈 然后新的方法方法进栈

随机推荐

  1. Elasticsearch---DSL搜索实践

    Domain Specific Language 特定领域语言,基于JSON格式的数据查询,查询更灵活,有利于复杂查询 一.普通url路径参数搜索 数据准备 1.建立名字为 shop 的索引 2.手动 ...

  2. 【转载】Win10彻底格式化磁盘防止数据恢复的技巧

    转载地址 注意 要尽量删除数据,请在运行cipher /w时关闭其他所有应用程序. 1.如果你在格式化磁盘后想要防止数据被恢复, Format 命令,而现在只需在其后添加 /P 参数,即可用随机数据覆 ...

  3. springCloud中的注册中心Nacos

    springCloud中的注册中心Nacos 三个模块: 1.注册中心 2.服务提供者(生产者) 提供服务 3.服务消费者(消费者)调用服务 流程:消费者和生产者都要向注册中心注册,注册的是二者中服务 ...

  4. luogu4464:莫比乌斯反演,积性函数和伯努利数

    题目链接:https://www.luogu.com.cn/problem/P4464 简记$gcd(x,y)=(x,y)$. 推式子: $\sum_{i=1}^{n}{(i,n)^xlcm(i,n) ...

  5. Android 开发学习进程0.28 腾讯TBS接入和相关问题

    TBS 的接入和使用 TBS 的接入 腾讯TBS是X5内核的升级版,可以当作webview 来打开 网页,可以以用来打开docx doc pdf 等文件,这里主要使用的是文件功能. 依赖接入 api ...

  6. MySQL学习笔记(五)

    倒数第二天!冲冲冲!!! 一.索引 一个表里面可以有多个索引. 1. 索引的作用:约束与加速查找 无索引:从前到后依次查找 有索引:会为索引列创造一个额外文件(以某种格式存储).在使用索引进行查找时, ...

  7. CVE-2016-5734-phpmyadmin-4.0.x-4.6.2-代码执行

    参考 https://www.jianshu.com/p/8e44cb1b5b5b 漏洞原因 phpMyAdmin是一套开源的.基于Web的MySQL数据库管理工具.在其查找并替换字符串功能中,将用户 ...

  8. 通达OA 页面敏感信息-2013/2015版本

    参考 http://wiki.0-sec.org/0day/%E9%80%9A%E8%BE%BEoa/4.html 漏洞影响 2013.2015版本 复现过程 POC: http://0-sec.or ...

  9. SQL驱动限制,导致插入失败

    insert into TB_IF_ORDERS (DC_CD,JOB_DT,SEQ_NO,ORDER_KEY,ORDER_ID,ORDER_LINE_NUM,COMPANY_CD,CUST_CD,S ...

  10. Java小tips之命令行传参

    在命令行运行主函数时,后缀字符串,则会储存在args[]数组中,这种方法可以在程序运行时,借助Main函数传参 主类书写不规范见谅 ```java public class hello{ public ...