IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> android R版本AppTransition动效源码分析 -> 正文阅读

[开发测试]android R版本AppTransition动效源码分析

????????AppTransition代表activity组件的切换过程,启动或是退出activity都会执行AppTransition,Android系统定义了多达十几种应用的transition类型,这些类型定义具体可参考WindowManager类。本文以TRANSIT_TASK_OPEN类型为例,场景以桌面点击图库冷启动为例。

以下文中AppTransition相关日志均需要执行命令开启输出到applogcat之中,正式商用版本也都可以以此方式打开:

adb shell wm logging enable-text WM_DEBUG_APP_TRANSITIONS?WM_DEBUG_REMOTE_ANIMATIONS

其中,WM_DEBUG_APP_TRANSITIONS代表开启的是AppTransition相关日志;WM_DEBUG_REMOTE_ANIMATIONS表示开启的是RemoteAnimation相关的日志,桌面打开动效使用的就是RemoteAnimation。

一、冷启动跳转新应用

1、prepareAppTransition准备阶段

? ? ? ? 在startActivity阶段会调用DisplayContent.prepareAppTransition去设置AppTransition类型为TRANSIT_TASK_OPEN,执行的是图中reusedTask为空分支。

09-08 09:42:05.169 ?1479 ?5339 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.wtf.gallery3d/.app.MainActivity bnds=[48,1681][294,1992] (has extras)} from uid 10100
09-08 09:42:05.179 ?1479 ?5339 V WindowManager: Prepare app transition: transit=TRANSIT_TASK_OPEN mNextAppTransition=TRANSIT_UNSET alwaysKeepCurrent=false displayId=0 Callers=com.android.server.wm.DisplayContent.prepareAppTransition:5168 com.android.server.wm.DisplayContent.prepareAppTransition:5162 com.android.server.wm.ActivityStack.startActivityLocked:2414 com.android.server.wm.ActivityStarter.startActivityInner:2246 com.android.server.wm.ActivityStarter.startActivityUnchecked:1987?

Prepare app transition日志中的transit是打算要设置的新transit,mNextAppTransition是当前已经存在的transit。

prepareAppTransition流程图如下:

该函数功能如下:

1)设置mNextAppTransition表明要执行的activity组件切换类型,设置值(非TRANSIT_UNSET值)后使得AppTransition.isTransitionSet()返回true表面已经设置了AppTransition。

2)该函数若重复执行,按其内部逻辑存在覆盖和不覆盖两种场景:覆盖场景常见的比如TRANSIT_TASK_OPEN替换掉TRANSIT_TASK_CLOSE、TRANSIT_ACTIVITY_OPEN 替换掉TRANSIT_ACTIVITY_CLOSE,也就是常说的open activity和open task的优先级要高于close activity和close task;不覆盖场景比如热启应用复用栈时会出现activityPaused阶段执行到resumeTop去设置TRANSIT_TASK_OPEN尝试替换掉startActivity阶段设置的TRANSIT_TASK_TO_FRONT,但不会被替换成功。

3)执行AppTransition.prepare()函数设置mAppTransitionState为APP_STATE_IDLE,即设置AppTransition的状态为IDLE空闲态,因为只有空闲状态才能执行下一个即将要执行的AppTransition。

完成这一步表明App Transition准备完成,但离动画执行还有十万八千里。

? ? ? ? 其实在activityPaused阶段去resumeTop时仍然会触发一次设置TRANSIT_TASK_OPEN,代码和日志如下:

09-08 09:42:05.191 ?1479 ?1495 V WindowManager: Prepare app transition: transit=TRANSIT_TASK_OPEN mNextAppTransition=TRANSIT_TASK_OPEN alwaysKeepCurrent=false displayId=0 Callers=com.android.server.wm.DisplayContent.prepareAppTransition:5168 com.android.server.wm.DisplayContent.prepareAppTransition:5162 com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked:2059 com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked:1710 com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities:2478

activityPaused阶段的resumeTop设置动效类型为TRANSIT_TASK_OPEN,针对startActivity场景其实该处设置无效,因为之前startActivity流程已经设置过,但是对于back键等途径触发的resumeTop场景的设置仍然有效。?

2、setVisibility阶段

? ? ? ? ActivityRecord.setVisibility函数的主要功能是把设置true的ActivityRecord加到DisplayContent.mOpeningApps列表,把设置false的ActivityRecord加到DisplayContent.mClosingApps列表,该函数在每次启动页面(不论热启冷起)的整个过程中可能涉及多次调用,是可重入的,且在执行DisplayContent.executeAppTransition之前都不会真正的commitVisibility(GOOD TO GO阶段才会真正执行),仅仅是填充mOpeningApps和mClosingApps,目的是在GOOD TO GO真正做动效时有目标的退场和入场应用去执行动效。

? ? ? ? 冷起时首次触发桌面加到mClosingApps、图库加到mOpeningApps是由activityPaused阶段的以下函数触发:

之前分析应用启动时曾说过,冷起新栈,由completePaused结束的那次ensureActivitiesVisible来触发将桌面makeInvisible进而触发ActivityRecord.setVisibility(false)加到mClosingApps、将图库makeVisibleAndRestartIfNeeded进而触发ActivityRecord.setVisibility(true)加到mOpeningApps。

图库ensure执行的分支:

09-08 09:42:05.192 ?1479 ?1495 V WindowManager: setAppVisibility(Token{5817814 ActivityRecord{7ddd3b9 u0 com.wtf.gallery3d/.app.MainActivity t5931}}, visible=true): mNextAppTransition=TRANSIT_TASK_OPEN visible=false mVisibleRequested=false Callers=com.android.server.wm.ActivityRecord.setVisibility:4405 com.android.server.wm.EnsureActivitiesVisibleHelper.makeVisibleAndRestartIfNeeded:223 com.android.server.wm.EnsureActivitiesVisibleHelper.setActivityVisibilityState:155 com.android.server.wm.EnsureActivitiesVisibleHelper.lambda$Bbb3nMFa3F8er_OBuKA7-SpeSKo:0 com.android.server.wm.-$$Lambda$EnsureActivitiesVisibleHelper$Bbb3nMFa3F8er_OBuKA7-SpeSKo.accept:12 com.android.internal.util.function.pooled.PooledLambdaImpl.doInvoke:307?

桌面ensure执行的分支:
09-08 09:42:05.192 ?1479 ?1495 V WindowManager: setAppVisibility(Token{6d196ad ActivityRecord{e45e1e5 u0 com.wtf.launcher/.Launcher t5815}}, visible=false): mNextAppTransition=TRANSIT_TASK_OPEN visible=true mVisibleRequested=true Callers=com.android.server.wm.ActivityRecord.setVisibility:4405 com.android.server.wm.ActivityRecord.makeInvisible:5168 com.android.server.wm.EnsureActivitiesVisibleHelper.setActivityVisibilityState:182 com.android.server.wm.EnsureActivitiesVisibleHelper.lambda$Bbb3nMFa3F8er_OBuKA7-SpeSKo:0 com.android.server.wm.-$$Lambda$EnsureActivitiesVisibleHelper$Bbb3nMFa3F8er_OBuKA7-SpeSKo.accept:12 com.android.internal.util.function.pooled.PooledLambdaImpl.doInvoke:307

虽然activityPaused中的completePaused可以最终触发到桌面和图库的ActivityRecord.setVisibility,但由于是冷起栈,realStartActivityLocked阶段仍然可以触发要启动的图库执行一次ActivityRecord.setVisibility(true),且该次才是最关键的一次,日志如下:

09-08 09:42:05.235 ?1479 ?4303 V WindowManager: setAppVisibility(Token{5817814 ActivityRecord{7ddd3b9 u0 com.wtf.gallery3d/.app.MainActivity t5931}}, visible=true): mNextAppTransition=TRANSIT_TASK_OPEN visible=false mVisibleRequested=true Callers=com.android.server.wm.ActivityRecord.setVisibility:4405 com.android.server.wm.ActivityStackSupervisor.realStartActivityLocked:881 com.android.server.wm.RootWindowContainer.startActivityForAttachedApplicationIfNeeded:2139 com.android.server.wm.RootWindowContainer.lambda$5fbF65VSmaJkPHxEhceOGTat7JE:0 com.android.server.wm.-$$Lambda$RootWindowContainer$5fbF65VSmaJkPHxEhceOGTat7JE.apply:8 com.android.internal.util.function.pooled.PooledLambdaImpl.doInvoke:315

而无论是冷启还是热启,都会执行ActivityRecord.completeResumeLocked,该函数同样会把要resume的页面执行ActivityRecord.setVisibility(true),虽然对于冷起场景此次调用属于多余的操作,但是对于热启复用栈场景该处很关键,因为热启场景不会调用realStartActivityLocked但是仍然会调用completeResumeLocked,冷启场景日志如下:

09-08 09:42:05.239 ?1479 ?4303 V WindowManager: setAppVisibility(Token{5817814 ActivityRecord{7ddd3b9 u0 com.wtf.gallery3d/.app.MainActivity t5931}}, visible=true): mNextAppTransition=TRANSIT_TASK_OPEN visible=false mVisibleRequested=true Callers=com.android.server.wm.ActivityRecord.setVisibility:4405 com.android.server.wm.ActivityRecord.completeResumeLocked:5373 com.android.server.wm.ActivityStack.minimalResumeActivityLocked:1028 com.android.server.wm.ActivityStackSupervisor.realStartActivityLocked:1020 com.android.server.wm.RootWindowContainer.startActivityForAttachedApplicationIfNeeded:2139 com.android.server.wm.RootWindowContainer.lambda$5fbF65VSmaJkPHxEhceOGTat7JE:0

3、executeAppTransition阶段

? ? ? ? 无论是冷启还是热启,都是由ActivityRecord.completeResumeLocked阶段触发的DisplayContent.executeAppTransition来最终执行AppTransition,当然此处仅是执行AppTransition,并不代表能一定执行动效,因为动效的执行需要依赖mOpeningApps中的应用绘制完成才能够执行。DisplayContent.executeAppTransition功能如下:

1)首先调用AppTransition.isTransitionSet()判断是否有设置transit,若未设置则该函数不产生任何作用。

2)调用AppTransition.setReady()函数将mAppTransitionState从APP_STATE_IDLE状态切换到APP_STATE_READY,只有ready之后才有可能触发GOOD TO GO流程,ready之前就算窗口绘制完毕(假设有此异常流程)也无法执行到GOOD TO GO。

09-08 09:42:05.240 ?1479 ?4303 W WindowManager: Execute app transition: mNextAppTransition=TRANSIT_TASK_OPEN, displayId: 0 Callers=com.android.server.wm.RootWindowContainer.executeAppTransitionForAllDisplay:2399 com.android.server.wm.ActivityStackSupervisor.reportResumedActivityLocked:2092 com.android.server.wm.ActivityRecord.completeResumeLocked:5402 com.android.server.wm.ActivityStack.minimalResumeActivityLocked:1028 com.android.server.wm.ActivityStackSupervisor.realStartActivityLocked:1020

4、GOOD TO GO阶段

? ? ? ? 执行完executeAppTransition并不一定立马就能触发动效的执行,需要等要打开的ActivityRecord窗口绘制完成(有starting window的只需要starting window绘制完成,不需要等到主窗口绘制完成),才能触发GOOD TO GO真正执行动画。GOOD TO GO执行动画流程如下:

在wms每次触发performSurfacePlacement刷新surface时,都会尝试检查下DisplayContent是否有设置了动画且满足Ready状态、要做动画的应用是否绘制完成,如果这些条件都满足则进入GOOD TO GO阶段去apply动效真正执行动效。

二、热启动跳转新应用

1、prepareAppTransition准备阶段

? ? ? ? 在startActivity阶段会调用DisplayContent.prepareAppTransition去设置AppTransition类型为TRANSIT_TASK_TO_FRONT,执行的是前文中startActivity流程的reusedTask非空分支。

09-08 09:42:07.711 ?1479 ?4064 I ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.wtf.gallery3d/.app.MainActivity bnds=[48,1681][294,1992] mCallingUid=10100} from uid 10100 and from pid 3367
09-08 09:42:07.715 ?1479 ?4064 V WindowManager: Prepare app transition: transit=TRANSIT_TASK_TO_FRONT mNextAppTransition=TRANSIT_UNSET alwaysKeepCurrent=false displayId=0 Callers=com.android.server.wm.DisplayContent.prepareAppTransition:5168 com.android.server.wm.ActivityStack.updateTransitLocked:2805 com.android.server.wm.ActivityStack.moveTaskToFront:2900 com.android.server.wm.ActivityStarter.setTargetStackIfNeeded:3156 com.android.server.wm.ActivityStarter.recycleTask:2450

在activityPaused阶段去resumeTop时仍然如冷起场景一样都会执行重新设置transit的动作:

09-08 09:42:07.741 ?1479 ?3574 V WindowManager: Prepare app transition: transit=TRANSIT_TASK_OPEN mNextAppTransition=TRANSIT_TASK_TO_FRONT alwaysKeepCurrent=false displayId=0 Callers=com.android.server.wm.DisplayContent.prepareAppTransition:5168 com.android.server.wm.DisplayContent.prepareAppTransition:5162 com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked:2059 com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked:1710 com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities:2478?
但由于我们前面介绍过prepareAppTransition虽然被重复执行,但TRANSIT_TASK_OPEN不能覆盖掉TRANSIT_TASK_TO_FRONT。

2、setVisibility阶段

? ? ? ? 热启场景在activityPaused阶段执行resumeTop时就会把pause成功的桌面执行setVisibility(false)加到mClosingApps、把要resume的图库执行setVisibility(true)加到mOpeningApps,而不需要依赖completePaused结束的那次ensureActivitiesVisible。

resumeTop时图库被setVisibility(true):

09-08 09:42:07.742 ?1479 ?3574 V WindowManager: setAppVisibility(Token{5817814 ActivityRecord{7ddd3b9 u0 com.wtf.gallery3d/.app.MainActivity t5931}}, visible=true): mNextAppTransition=TRANSIT_TASK_TO_FRONT visible=false mVisibleRequested=false Callers=com.android.server.wm.ActivityRecord.setVisibility:4405 com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked:2141 com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked:1710 com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities:2478 com.android.server.wm.ActivityStack.completePauseLocked:1370 com.android.server.wm.ActivityRecord.activityPaused:5475?

resumeTop时桌面被setVisibility(false):

09-08 09:42:07.745 ?1479 ?3574 V WindowManager: setAppVisibility(Token{6d196ad ActivityRecord{e45e1e5 u0 com.wtf.launcher/.Launcher t5815}}, visible=false): mNextAppTransition=TRANSIT_TASK_TO_FRONT visible=true mVisibleRequested=true Callers=com.android.server.wm.ActivityRecord.setVisibility:4405 com.android.server.wm.ActivityRecord.makeInvisible:5168 com.android.server.wm.EnsureActivitiesVisibleHelper.setActivityVisibilityState:182 com.android.server.wm.EnsureActivitiesVisibleHelper.lambda$Bbb3nMFa3F8er_OBuKA7-SpeSKo:0 com.android.server.wm.-$$Lambda$EnsureActivitiesVisibleHelper$Bbb3nMFa3F8er_OBuKA7-SpeSKo.accept:12 com.android.internal.util.function.pooled.PooledLambdaImpl.doInvoke:307

热启场景resumeTop最终也会执行ActivityRecord.completeResumeLocked,同样还会重复执行一次setAppVisibility,可以认为热启场景,completeResumeLocked引发的此次setAppVisibility是最关键的一次

09-08 09:42:07.746 ?1479 ?3574 V WindowManager: setAppVisibility(Token{5817814 ActivityRecord{7ddd3b9 u0 com.wtf.gallery3d/.app.MainActivity t5931}}, visible=true): mNextAppTransition=TRANSIT_TASK_TO_FRONT visible=false mVisibleRequested=true Callers=com.android.server.wm.ActivityRecord.setVisibility:4405 com.android.server.wm.ActivityRecord.completeResumeLocked:5373 com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked:2273 com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked:1710 com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities:2478 com.android.server.wm.ActivityStack.completePauseLocked:1370?

3、executeAppTransition阶段

? ? ? ? 无论是冷启还是热启,都是由ActivityRecord.completeResumeLocked阶段触发的DisplayContent.executeAppTransition来最终执行AppTransition,不同的是热启阶段触发的completeResumeLocked不是由realStartActivityLocked和minimalResumeActivityLocked触发,而是由resumeTop直接触发。

09-08 09:42:07.746 ?1479 ?3574 W WindowManager: Execute app transition: mNextAppTransition=TRANSIT_TASK_TO_FRONT, displayId: 0 Callers=com.android.server.wm.RootWindowContainer.executeAppTransitionForAllDisplay:2399 com.android.server.wm.ActivityStackSupervisor.reportResumedActivityLocked:2092 com.android.server.wm.ActivityRecord.completeResumeLocked:5402 com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked:2273 com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked:1710

4、GOOD TO GO阶段

? ? ? ? 此阶段与冷启场景动效执行流程一样,不再赘述。

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-09-11 00:03:26  更:2021-09-11 00:03:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/21 5:43:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码