前言
在王小二图解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信号到来的时候触发渲染的代码。
思考
如果你们有其他想法可以获得屏幕的帧率,也可以回复留言。
网友评论