ViewRootImpl#applyTransactionOnDraw 的坑
前情提要
之前在帮一同事做 SurfaceView
相关的内容(他本人对 SurfaceControl
相关接口不太熟悉)。在即将解决需要使用到帧同步接口的时候, 无意间看到了 SurfaceView
使用到了 ViewRootImpl#applyTransactionOnDraw
来做帧同步内容。
1 | private void applyTransactionOnVriDraw(Transaction t) { |
我一看好啊,以前老是写这种代码来做帧同步:
1 | viewRoot.registerRtFrameCallback(frame -> { |
虽然不怎么麻烦,但是贯彻简洁主义的我是这样想的:两次方法调用 < 一次方法调用。于是在简单看了下这接口的实现之后就决定以后就用这接口了。
遇到的问题
后面在做桌面动画需求的时候,鉴于我喜欢偷懒,于是也直接使用了这个接口来同步动画结束时的 finishTransaction
。但在测试频繁打断动画的时候 却发现了动画结束的时候居然会闪一下,看着就像没帧同步的样子(信念崩塌)。
于是赶紧去仔细看了下这个接口的实现,好家伙,原来这接口只是保证了 Transaction
一定能生效,但可能是通过帧同步生效的,并不一定。 具体是怎么合并到 BLASTBufferQueue
的,可以自行看一下 ViewRootImpl#registerCallbacksForSync
这个方法,我们只需要看帧同步不生效的原因就行了:
1 | // 具体在 ViewRootImpl#performTraversal 里 |
好嘛,安排得明明白白,注释都写好了:为了避免事务状态丢失,提前调用 apply
,闪一两帧总好过状态不对。
结尾
能怎么办,老实用回之前一直在用的帧同步方法呗。不过以后用这些接口的时候,还是得好好看下注释,没有注释就看下具体实现,避免再出现这种踩坑的问题。
ViewRootImpl#applyTransactionOnDraw 的坑
https://gitofleonardo.github.io/2025/05/27/Android_caution_applyTransactionOnDraw/