登录

去注册

登录

注册

去登录

注册

每日一问 很多时候我们说"Android16.6ms刷新一次屏幕" 正确吗?

xiaoyang   2019-07-30   收藏

大家都知道,很多时候我们说"Android16.6ms刷新一次屏幕"

那么问题是:

这个16.6ms刷新一次屏幕是什么意思呢?是每隔16.6ms都会调用一次View的onDraw么?

如果不是?

那是什么样的一个刷新机制,这个机制在Android版本迭代中有无变化。

本周1/3,现在问答支持markdown啦,自由玩耍吧。

10

哈哈哈,终于支持markdown啦

每过16.6ms都会回调一次View的onDraw方法吗?

不是的,这个频率,说的是系统发出屏幕刷新信号频率(但我也不太确定是不是真的16.6ms(在源码里没看到过)),但是在onDraw中收到回调的时机,是不确定的(各种原因,如代码写法、设备性能等)。

那它的刷新机制是怎样的呢?

屏幕刷新大致流程:

  1. View调用invalidate方法;
  2. ViewRootImpl会把doTraversal任务(处理View的测量、布局、绘制),post到Choreographer中(在系统下一次发出同步信号的时候,这个doTraversal任务会被执行);
  3. Choreographer会借助DisplayEventReceiver的scheduleVsync方法,在native层(IDisplayEventConnection.cpp)通过Binder(跨进程)发出一个REQUEST_NEXT_VSYNC的Tag(发去了哪里不知道,我找不到那个类);
  4. 在DisplayEventDispatcher.cpp中,会看到一个handleEvent方法(可以猜测,系统在下一次发出屏幕刷新信号时,(间接或直接)回调的就是这个方法),它里面会调用android_view_DisplayEventReceiver.cpp中的dispatchVsync方法,这个方法最终去了哪里呢?
  5. 回到java层,在DisplayEventReceiver中会看到一个同名同签名的dispatchVsync方法,并且上面有注释写着:Called from native code. (可以知道,这个方法是在native层被调用的),它里面会调用onVsync方法,
  6. onVsync方法在Choreographer中内部类的实现,最终是会调用doFrame方法的,这个doFrame方法,里面会把刚刚在ViewRootImpl中post到Choreographer里的doTraversal任务(处理View的测量、布局、绘制)执行!!。

以上提到的native层代码,分别(按顺序)在以下链接中能看到:

这个机制在版本迭代中有何变化?

刚刚分别试了下手头上的6.0和9.0系统的测试机,
在一个自定义View中的onDraw方法不断invalidate和打印被回调的时间:

    private long lastTime;

    @Override
    public void onDraw(Canvas canvas) {
        LogUtil.print(SystemClock.uptimeMillis() - lastTime);
        lastTime = SystemClock.uptimeMillis();
        invalidate();
    }

发现在6.0的手机是上这样的(随机截取20条log):

onDraw: 14
onDraw: 0
onDraw: 13
onDraw: 0
onDraw: 14
onDraw: 1
onDraw: 14
onDraw: 1
onDraw: 13
onDraw: 0
onDraw: 14
onDraw: 1
onDraw: 14
onDraw: 1
onDraw: 13
onDraw: 1
onDraw: 10
onDraw: 1
onDraw: 12
onDraw: 1

而9.0系统的手机是这样的(随机截取20条log):

onDraw: 15
onDraw: 15
onDraw: 15
onDraw: 15
onDraw: 15
onDraw: 15
onDraw: 15
onDraw: 15
onDraw: 16
onDraw: 15
onDraw: 15
onDraw: 16
onDraw: 15
onDraw: 15
onDraw: 15
onDraw: 15
onDraw: 15
onDraw: 14
onDraw: 15
onDraw: 15

可以看到,在6.0系统上,好像有个缓存机制,不断地invalidate的话,每两次中有一次是<=1ms就回调了,可以猜想这一次没有等待系统的屏幕刷新信号就直接回调了onDraw方法。
而9.0系统则比较稳定,onDraw方法每一次被回调都间隔了15ms左右.

回复
0
  1. 是指在界面显示 UI 更新的时侯为了提供流畅的体验效果,需要每隔 16.6ms 对屏幕上的 UI 元素进行重绘,如果重绘时间大于 16.6ms UI 界面就会产产生卡顿。那么原因是为什么呢?
     原因:在于人的是感观,以及动态模糊等因素,如果屏幕的刷新速率低于每秒 60 (也就是 16.6ms 刷新一次屏幕)帧人就会有卡顿的感觉。
    
  2. 并不会每次都会调用 View 的 onDraw 方法,当界面 UI 在静止的情况下,虽然16.6 ms 刷新机制依然存在,但是此时屏幕会取用缓存中的数据进行显示,不会再去调用 view 的 ondraw 进行重绘。而且如果此时 View 处于不可见状态也不会调用 ondraw。
  3. 版本迭代...找找资料看看。get 一波
回复

删除留言

确认删除留言,会导致相关评论丢失?

取消 确定