Android 理解requestStartTransition过渡动画

Android系统Shell过渡动画流程解析

摘要:本文详细分析了从Activity启动到Shell动画执行的完整流程。关键节点包括:1) ActivityStarter创建并收集Transition;2) 通过TransitionController将Transition请求发送到wm/shell进程;3) Shell端接收请求并执行动画;4) 动画完成后通知WMS使Activity进入RESUMED状态。流程涉及跨进程通信(通过ITransitionPlayer接口),并对比了传统过渡与Shell过渡的区别。核心控制点在TransitionController的requestStartTransition方法,该方法通过Binder调用将TransitionToken传递给Shell进程,触发后续动画执行。整个过程体现了Android窗口管理系统与Shell组件的协同工作机制。

启动动画到 wm/shell 的完整流程

复制代码
┌─────────────────────────────────────────────────────────────────────────────┐
│                   Activity 启动 → Shell动画 流程                             │
└─────────────────────────────────────────────────────────────────────────────┘

1️⃣ [ActivityStarter.executeRequest]  Line ~1510
    │
    │  创建Transition并开始收集
    ▼
    Transition newTransition = r.mTransitionController.createAndStartCollecting(TRANSIT_OPEN)
         │
         │  如果Shell Transitions启用,创建Transition
         │
         ▼
2️⃣ [ActivityStarter.startActivityInner]  Line 1875
    │
    │  执行启动逻辑,Activity被添加到Task
    │
    ▼
3️⃣ [ActivityStarter.handleStartResult]  Line 1732
    │
    │  核心:发送Transition到Shell
    ▼
    if (isIndependentLaunch && transition != null) {
        transitionController.requestStartTransition(transition, ...);
    }
         │
         │  ◄── 这里!Transition被发送到Shell!
         │
         ▼
4️⃣ [TransitionController.requestStartTransition]  Line 805
    │
    │  获取Shell的ITransitionPlayer代理
    ▼
    mTransitionPlayers.getLast().mPlayer.requestStartTransition(
            transition.getToken(),  // Transition token
            request);               // TransitionRequestInfo
         │
         │  ◄── 跨进程Binder调用到 wm/shell 进程
         │
         ▼
5️⃣ [Shell端 - ITransitionPlayer stub]
    │
    │  Shell接收Transition请求
    ▼
    TransitionPlaybackController 或 ShellTransitionPlayback
         │
         │  执行动画
         ▼
6️⃣ 动画完成 ──→ 通知WMS ──→ Activity变成RESUMED

创建Transition - ActivityStarter.java:1511-1512

复制代码
final Transition newTransition = r.mTransitionController.isShellTransitionsEnabled()
        ? r.mTransitionController.createAndStartCollecting(TRANSIT_OPEN) : null;

触发条件 :只有当 isShellTransitionsEnabled() 返回 true 时才使用 Shell Transitions

发送到Shell - ActivityStarter.java:1838-1842

复制代码
if (isIndependentLaunch && transition != null) {
    transitionController.requestStartTransition(transition,
            mTargetTask == null ? started.getTask() : mTargetTask,
            remoteTransition, null /* displayChange */);
}

触发条件 :

  • isIndependentLaunch - 独立启动(不是从属启动)

  • transition != null - Transition存在

Shell接收Transition - TransitionController.java:858-859

复制代码
mTransitionPlayers.getLast().mPlayer.requestStartTransition(
        transition.getToken(), request);

mTransitionPlayers 是 Shell 进程注册的 ITransitionPlayer 代理列表

完整时序图

复制代码
┌──────────────┐     ┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   App进程   │     │  system_server│     │  wm/shell   │     │ SurfaceFlinger│
│              │     │              │     │   进程       │     │              │
└──────┬───────┘     └──────┬───────┘     └──────┬───────┘     └──────┬───────┘
       │                    │                    │                    │
       │ startActivity()    │                    │                    │
       │───────────────────▶│                    │                    │
       │                    │                    │                    │
       │                    │ createAndStartCollecting(TRANSIT_OPEN)   │
       │                    │──────────┐          │                    │
       │                    │          │          │                    │
       │                    │◀─────────┘          │                    │
       │                    │                    │                    │
       │                    │ startActivityInner()│                    │
       │                    │  添加Activity到Task│                    │
       │                    │                    │                    │
       │                    │ requestStartTransition()                 │
       │                    │───────────────────▶│                    │
       │                    │                    │                    │
       │                    │                    │ 收到TransitionToken│
       │                    │                    │──────────┐         │
       │                    │                    │          │         │
       │                    │                    │◀─────────┘         │
       │                    │                    │                    │
       │                    │                    │ 执行动画...         │
       │                    │                    │───────────────────▶│
       │                    │                    │                    │
       │                    │                    │        动画显示     │
       │                    │                    │                    │
       │                    │◀───────────────────│ 动画完成            │
       │◀──────────────────│   onAnimationDone  │                    │
       │                    │                    │                    │
       │  Activity RESUMED │                    │                    │
       │                    │                    │                    │

Shell Transitions 架构

复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                     Shell Transitions 架构                               │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  system_server (WMS)              │        wm/shell 进程                 │
│  ┌─────────────────────────┐     │    ┌─────────────────────────┐      │
│  │   TransitionController  │     │    │  TransitionPlayback     │      │
│  │                         │     │    │  Controller             │      │
│  │  • mTransitionPlayers   │─────┼───▶│  • requestStartTransition│      │
│  │  • mCollectingTransition│     │    │  • playAnimation        │      │
│  │  • mPlayingTransitions │     │    │  • onAnimationDone      │      │
│  └─────────────────────────┘     │    └─────────────────────────┘      │
│                                   │              │                      │
│  ┌─────────────────────────┐     │              ▼                      │
│  │   Transition            │     │    ┌─────────────────────────┐      │
│  │                         │     │    │  ShellTransitionModel   │      │
│  │  • mToken (IBinder)     │     │    │                       │      │
│  │  • mType (TRANSIT_OPEN) │     │    │  • WallpaperCanvas     │      │
│  │  • mSyncId              │     │    │  • RemoteAnimationRunner│      │
│  └─────────────────────────┘     │    └─────────────────────────┘      │
│                                   │              │                      │
└───────────────────────────────────┼──────────────┼──────────────────────┘
                                    │              │
                                    ▼              ▼
                         ┌─────────────────────────────────────┐
                         │        SurfaceFlinger               │
                         │                                     │
                         │  接收各层Surface,                  │
                         │  合成并输出到显示屏幕                 │
                         └─────────────────────────────────────┘

系统级开关 - WindowManagerService.java:450

复制代码
public static final boolean sEnableShellTransitions = getShellTransitEnabled();

Activity级别开关 - ActivityOptions

复制代码
// 通过ActivityOptions设置自定义动画
options.setRemoteTransition(remoteTransition);

// 或者使用自定义Transition
options.setTransitionOwners(remoteTransition);

Legacy vs Shell 对比

实际动画执行点

当你点击桌面图标启动一个App时:

复制代码
1. Launcher Activity 发起 startActivity()
        │
        ▼
2. ActivityStarter 创建 TRANSIT_OPEN 类型的 Transition
        │
        ▼
3. handleStartResult() 调用 requestStartTransition()
        │
        ▼
4. Binder 调用到 wm/shell 的 ITransitionPlayer
        │
        ▼
5. Shell 端的 TransitionPlaybackController 执行:
   ├── 计算动画参数(起始位置、结束位置、时长)
   ├── 创建动画Surface
   ├── 控制Surface显示/隐藏/变换
   └── 完成后通知WMS
        │
        ▼
6. 动画结束 → Activity变成RESUMED状态
相关推荐
xiaoshiquan12068 分钟前
Gradle 复合构建:宿主项目直接依赖 SDK 源码模块的配置实践
android
小师兄吃牛肉2 小时前
Android Studio 2025 专业介绍:新特性、性能与开发体验全面解析
android·ide·android studio
美摄科技2 小时前
安卓离线类美颜特效SDK
android
fengci.4 小时前
BUUCTF(困难部分)
android·开发语言·前端·学习·php
传奇开心果6 小时前
【Compose Multiplatform跨端声明式UI实用技术】第9课:跨平台 ViewModel 与状态架构
android·kotlin
用户69371750013846 小时前
当你向领导申请 AI 编程工具预算时,如果领导追问“能提效多少,有量化数据吗”,你该怎么回答?
android·后端·ios
hunterandroid7 小时前
WorkManager 后台任务调度实战:从一次性任务到周期执行
android
事圆则缓7 小时前
Android 屏幕适配的前世今生
android
andyweike8 小时前
kotlin dsl library工程怎么配置
android·开发语言·kotlin
啵啵啵鱼8 小时前
九、JDBC 操作 MySQL 数据库
android·数据库·mysql