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。

该函数功能如下:

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

  • 16
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值