前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[037]Choreographer Skipped含义再探

[037]Choreographer Skipped含义再探

作者头像
王小二
发布2020-06-08 12:06:40
8490
发布2020-06-08 12:06:40
举报
文章被收录于专栏:王小二的Android站

前言

[036]Choreographer Skipped真正含义中,我介绍了一种可以产生Choreographer Skipped的情况。就是在onVsync被调用之前,往主线程post的一个Message。那还有没有其他方式可以产生这个Choreographer Skipped呢?

一、仔细看看代码

代码语言:javascript
复制
@Override
public void onVsync(long timestampNanos, long physicalDisplayId, int frame) {
    ...
    //onVsync方法将会在Vsync信号接收之后被回调
    //mTimestampNanos就是这次Vsync信号接收的时间
    mTimestampNanos = timestampNanos;
    mFrame = frame;
    //往主线程的Looper中投放一个Asynchronous的Message,callback为this
    //这个Message被处理的时候就会调用下面run-doFrame的方法
    Message msg = Message.obtain(mHandler, this);
    msg.setAsynchronous(true);
    mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
}

请注意onVsync参数中timestampNanos,这个值代表什么呢,其实代表的是Vsync信号到达App的时间,Vsync信号在通过socket通信发给App时候,会带上这个时间戳timestampNanos,这个过程其实是不会受主线程影响的。

在Vsync信号到来之后,onVsync方法没有被立刻调用,也可以产生Choreographer Skipped

二、写个Demo验证一下

代码语言:javascript
复制
public class Main2Activity extends AppCompatActivity implements View.OnClickListener {

    private TextView mTxtView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        mTxtView = findViewById(R.id.txt_view);
        mTxtView.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        mTxtView.setText("请求Vsync信号");//会触发scheduleTraversals,所以16ms以内会接受到Vsync信号
        try {
            Thread.sleep(1000);//这样子onVsync会推迟1000ms,才能被调用
        } catch (Exception e) {

        }
    }
}

注意我这里采用的是TextView,因为TextView点击没有UI刷新,所以不会触发scheduleTraversals,我在onClick中主动调用mTxtView.setText,会触发scheduleTraversals,所以App会在16ms以内会接受到Vsync信号,请注意16ms以内,时间不固定。

Vsync信号到来的时间点就是onVsync的形参timestampNanos。

然后mTxtView.setText完了之后再sleep 1000ms,处理完onClick代码。主线程会去处理onVsync的方法,由于Vsync信号早就到了,所以就算此时onVsync投放的Asynchronous的Message被立刻处理,但是已经晚了,所以还是会出现Choreographer Skipped。

代码语言:javascript
复制
D KobeWang2: onClick : start
D KobeWang2: onClick : end
I Choreographer: Skipped 60 frames!  The application may be doing too much work on its main thread.

三、总结

其实有很多Demo可以产生Choreographer Skipped,但是不管你怎么写,肯定是下面两种场景之一。

3.1 场景一

[036]Choreographer Skipped真正含义里介绍的Demo,虽然Vsync信号到了,onVsync被及时调用,但是主线程中有未开始处理的耗时Message,推迟了doFrame的执行时间。

场景一

3.2 场景二

本文介绍的Demo,Vsync信号早早到了,但是由于主线程的耗时操作,onVsync无法被及时调用

场景二

3.3 更正

更正一下我在[036]Choreographer Skipped真正含义说的话

Choreographer Skipped真正反映的是onVsync和doFrame两个方法调用的时间间隔

修正为

Choreographer Skipped真正反映的是Vsync信号到达App的时间和doFrame方法调用的时间间隔

场景一和场景二,只不过是通过两种方式增大了这个时间间隔而已。

3.4 onVsync被调用

我无数次的提到onVsync被调用,那到底onVsync是怎么被调用的,其实主线程的Looper.loop中一次循环会先处理native层监听的vsync信号和Input事件,处理一次java层的Message,就是类似这样子的伪代码。

代码语言:javascript
复制
public void loop() {
    for(;;) {
        //处理native层的任务,处理完所有vsync信号,input事件。
        //如果发现Vsync信号已经抵达APP,就会通过JNI回调onVsync方法
        doNativeTasks();
        //处理java层的Message,一次处理只能处理一个Message
        doJavaTasks();
    }
}

从主线程的Looper角度分析场景一和场景二的流程图如下:

充分展示了Vsync黄色块和doFrame紫色块之间的时间间隔是怎么被增大的。

尾巴

还记得神雕侠侣中找到情花毒解药的天竺神僧嘛,他先让自己中毒,才找到解药。所以我们在解决一些疑难BUG的时候,需要学会如何制造BUG,才能了解BUG产生的原理,才能找到解决BUG的方案。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、仔细看看代码
  • 二、写个Demo验证一下
  • 三、总结
    • 3.1 场景一
      • 3.2 场景二
        • 3.3 更正
          • 3.4 onVsync被调用
          • 尾巴
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档