美文网首页
[029]如何获取屏幕帧率

[029]如何获取屏幕帧率

作者: 王小二的技术栈 | 来源:发表于2020-02-27 00:10 被阅读0次

    前言

    王小二图解Android【006】高帧率屏幕这期的视频中,我给大家揭秘今年所有安卓旗舰都会吹的高帧率屏幕,其实高帧率屏幕不需要应用开发人员去主动适配,只要应用能在当前的硬件配置下,规定时间(1s/屏幕帧率)中完成一帧的绘制就可以了。

    那肯定有人就要问了,能否当前获得屏幕帧率,然后对高帧率屏幕做针对性优化,在有限的时间内完成一帧的绘制。

    一、标准SDK接口

    很简单,只要能够拿到WindowManager就可以获取。

    //this是Activity
    Log.v("Kobe", "Screen Hz is " + this.getWindowManager().getDefaultDisplay().getRefreshRate());
    
    02-26 23:31:50.526 18982 18982 V Kobe    : Screen Hz is 60.000004
    

    二、帧率约等于 1s/两次Vsync时间差

    public class MainActivity extends AppCompatActivity {
    
        private long firstVsync;
        private long secondVsync;
    
        private Choreographer.FrameCallback firstCallBack = new Choreographer.FrameCallback() {
            @Override
            public void doFrame(long frameTimeNanos) {
                firstVsync = frameTimeNanos;
                Choreographer.getInstance().postFrameCallback(secondCallBack);
            }
        };
    
        private Choreographer.FrameCallback secondCallBack = new Choreographer.FrameCallback() {
            @Override
            public void doFrame(long frameTimeNanos) {
                secondVsync = frameTimeNanos;
                //1s = 1000000000ns
                long hz = 1000000000 / (secondVsync - firstVsync);
                Log.v("Kobe", "Screen Hz is " + hz);
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            HandlerThread vSyncThread = new HandlerThread("Vsync");
            vSyncThread.start();
            Handler handler = new Handler(vSyncThread.getLooper());
            handler.post(new Runnable() {
                @Override
                public void run() {
                    Choreographer.getInstance().postFrameCallback(firstCallBack);
                }
            });
        }
    }
    

    原理就是利用Choreographer这个类的postFrameCallback的方法。调用postFrameCallback之后将会在下一个Vsync信号来的时候触发运行FrameCallback的doFrame,Vsync的上报时间就是形参frameTimeNanos(单位:纳秒)。

    long hz = 1000000000 / (secondVsync - firstVsync);
    

    简单的计算就可以算出来了。

    02-26 23:38:01.633 19234 19261 V Kobe    : Screen Hz is 59//大概的推测出是60hz的屏幕
    

    有没有发现上述代码中的两个细节

    1.Choreographer.getInstance()必须运行在有Looper的线程中。

    因为Vsync信号的监听是通过Looper中的epoll机制监听的。

    2.我没有使用主线程的Looper,而是另外新建HandlerThread。

    因为主线程的Looper比较忙,容易导致Vsync信号监听推迟,导致两次Vsync时间差不对。
    我之前没有另外新建HandlerThread,得到的结果是不固定的,而且是错的。

    02-26 23:22:29.374 18442 18442 V Kobe    : Screen Hz is 14
    02-26 23:31:21.079 18753 18753 V Kobe    : Screen Hz is 19
    
    如果听不懂,可以看我的视频

    王小二图解Android【001】Looper上篇
    王小二图解Android【002】Looper下篇

    三、总结

    一般来说用标准SDK接口就够了,为什么我要大费周章的讲方法2,其实是想让大家了解Choreographer的作用,因为在我们调用View的渲染中就是用到了这个类,在下一个Vsync信号到来的时候触发渲染的代码。

    思考

    如果你们有其他想法可以获得屏幕的帧率,也可以回复留言。

    相关文章

      网友评论

          本文标题:[029]如何获取屏幕帧率

          本文链接:https://www.haomeiwen.com/subject/jdewchtx.html