博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android性能:通过Choreographer检测UI丢帧和卡顿
阅读量:6534 次
发布时间:2019-06-24

本文共 2964 字,大约阅读时间需要 9 分钟。

                                         Android性能:通过Choreographer检测UI丢帧和卡顿

Android系统每隔16ms重绘UI界面,16ms是因为Android系统规定UI绘图的刷新频率60FPS。Android系统每隔16ms,发送一个系统级别信号VSYNC唤起重绘操作。1秒内绘制UI界面60次。每16ms为一个UI界面绘制周期。

平常所说的“丢帧”情况,并不是真的把绘图的帧给“丢失”了,也而是UI绘图的操作没有和系统16ms的绘图更新频率步调一致,开发者代码在绘图中绘制操作太多,导致操作的时间超过16ms,在Android系统需要在16ms时需要重绘的时刻由于UI线程被阻塞而绘制失败。如果丢的帧数量是一两帧,用户在视觉上没有明显感觉,但是如果超过3帧,用户就有视觉上的感知。丢帧数如果再持续增多,在视觉上就是所谓的“卡顿”。
丢帧是引起卡顿的重要原因。在Android中可以通过Choreographer检测Android系统的丢帧情况,以作为进一步分析卡顿的基础:

package zhangphil.test;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.Choreographer;import android.view.View;public class ANRActivity extends AppCompatActivity {    private MyFrameCallback mFrameCallback = new MyFrameCallback();    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Choreographer.getInstance().postFrameCallback(mFrameCallback);        setContentView(R.layout.activity_anr);        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                uiLongTimeWork();            }        });    }    public class MyFrameCallback implements Choreographer.FrameCallback {        private String TAG = "性能检测";        private long lastTime = 0;        @Override        public void doFrame(long frameTimeNanos) {            if (lastTime == 0) {                //代码第一次初始化。不做检测统计。                lastTime = frameTimeNanos;            } else {                long times = (frameTimeNanos - lastTime) / 1000000;                int frames = (int) (times / 16);                if (times > 16) {                    Log.w(TAG, "UI线程超时(超过16ms):" + times + "ms" + " , 丢帧:" + frames);                }                lastTime = frameTimeNanos;            }            Choreographer.getInstance().postFrameCallback(mFrameCallback);        }    }    private void uiLongTimeWork() {        try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

 

Choreographer周期性的在UI重绘时候触发,在代码中记录上一次和下一次绘制的时间间隔,如果超过16ms,就意味着一次UI线程重绘的“丢帧”。丢帧的数量为间隔时间除以16,如果超过3,就开始有卡顿的感知。

代码运行输出:

07-20 11:23:40.082 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):17ms , 丢帧:1

07-20 11:23:40.099 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):17ms , 丢帧:1
07-20 11:23:40.145 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):28ms , 丢帧:1
07-20 11:23:40.165 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):20ms , 丢帧:1
07-20 11:23:40.190 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):24ms , 丢帧:1
07-20 11:23:40.208 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):17ms , 丢帧:1
07-20 11:23:40.224 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):17ms , 丢帧:1
07-20 11:23:40.257 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):33ms , 丢帧:2
07-20 11:23:40.306 5654-5654/zhangphil.test W/性能检测: UI线程超时(超过16ms):24ms , 丢帧:1

 

如果手动点击按钮故意阻塞1秒,丢弃的帧数更多。

转载地址:http://pwkdo.baihongyu.com/

你可能感兴趣的文章
有向图的拓扑排序算法JAVA实现
查看>>
Android获取当前时间与星期几
查看>>
jenkins2 multibranch
查看>>
Css定位-定位
查看>>
am335x 电容屏驱动添加。
查看>>
rhel-server-7.2-x86_64无法联网(VMware环境)
查看>>
Nginx配置中的log_format用法梳理(设置详细的日志格式)
查看>>
优化LibreOffice如此简单
查看>>
【Oracle 数据迁移】环境oracle 11gR2,exp无法导出空表的表结构【转载】
查看>>
3D印花芭蕾舞鞋为舞者科学地保护双脚
查看>>
通过ActionTrail监控AccessKey的使用
查看>>
从 JavaScript 到 TypeScript
查看>>
一个mysql复制中断的案例
查看>>
Linux常用的服务器构建
查看>>
深入了解 Weex
查看>>
异构数据库
查看>>
把某一列值转换为逗号分隔字符串
查看>>
iOS中--NSArray调用方法详解 (李洪强)
查看>>
LINUX 常用命令整理
查看>>
“灾备全生态”全揭秘
查看>>