ViewManager 管理一个LIFO的 App 栈。栈底 App 不会因为打开了新 App 而销毁,只会暂停。
![]()
上半部是 push:B 先在 arena 中构造,等 fade 完成后才调 onEnter()。下半部是 pop:先执行退出回调和非拥有引用清理,再销毁 B 并恢复 A。
1 | push B: A.onPause() -> B 变为当前的drawable -> fade动画 -> B.onEnter() |
启动方式
1 | auto result = views.launch(appItem, parameters); |
launch() 用 AppItem 中的 factory,适合 AppLauncher 和注册系统。push<T>() 直接转发构造参数,适合已知具体类型的内部导航。
LaunchResult
| 结果 | 含义 |
|---|---|
Ok |
App 已构造并提交到栈 |
StackFull |
已达 PIXELUI_MAX_VIEW_DEPTH |
ArenaFull |
页面数未满,但 App 对象字节和对齐填充已放不下 |
ConstructionFailed |
factory 不能构造对象 |
TransitionInProgress |
正在页面提交或等待 fade 完成 |
容量失败是正常可观测结果,不应该被忽略。
不允许嵌套导航
onEnter()、onExit()、onPause()、onResume()、App 构造/析构以及导航输入中,不能同步再次 push/pop。ViewManager 使用 transition guard 稳定地拒绝嵌套请求,而不是在半完成的栈上继续操作。
如果生命周期回调需要去另一页,记录一个 pending action,在当前调用栈返回后由主循环执行。
fade 动画与 onEnter
从已显示 App push 新 App 时,新 App 先进入 m_pendingEnter。renderer() 继续推进 fade,最后一帧完成后才调用 onEnter()。这保证新 App 不会在上一页还可见时提前发布 Widget、Popup 或动画。
isTransitioning() 在等待 fade 时也返回 true,但 renderer 只会被短暂的 commit guard 挡住,否则 fade 自己会永远无法完成。
销毁前的清理
ViewManager 在 pop 时清理 drawable、exit callback、动画、Coroutine、Focus 和 Popup 引用,然后调用具体 App 析构函数并回滚 arena marker。App 查询得到的 IApplication* 不能跨过 pop 保存。
