如何同步到Android帧率

时间:2017-05-18 00:13:50

标签: java android frame synchronize

我正在寻找一种方法来将某些代码活动与Android显示帧速率同步。这是一小段代码,只需设置一个小显示区域的颜色,仅此而已。是否有某种方法或钩子可以用于此目的?

我可以使用以非常快的间隔成功运行的计时器,但渲染似乎会受到帧速率的混叠。例如,我的帧速率为60 Hz,因此如果我将定时器间隔设置为1/60秒,则外观不均匀。我无法将定时器设置为16.666毫秒,即使可以,我仍然会看到别名。

感谢。

2 个答案:

答案 0 :(得分:1)

经过一些搜索和实验,一个解决方案是使用Choreographer类,它提供了一种将回调函数挂钩到帧速率的方法。下面是代码。我发现它在慢速手机上显示出邋time的时机。近期型号的三星手机性能更佳。

private FrameCallback frameCallback = null;
private boolean frameCallbackPending = false;

public void armVSyncHandler() {
    if(!frameCallbackPending) {
        frameCallbackPending = true;
        if(frameCallback == null)
        {
            frameCallback = new FrameCallback() {
                @Override
                public void doFrame(long frameTimeNanos) {
                    frameCallbackPending = false;

                    // Do some work here

                    armVSyncHandler();
                }
            };
        }
        Choreographer.getInstance().postFrameCallback(frameCallback);
    }
}

答案 1 :(得分:1)

我知道这是一个古老的问题,但是我自己遇到了这个问题,并创建了一个很好的小实用程序类来实现此目的。

科特琳课:


/**
 * Small utility class that allows for [doFrame] to be executed every frame based on the native
 * [Choreographer] instead of using precomputed values and timers.
 * [doFrame] is run on the main thread and is executed on the next frame.
 * The [SyncedRenderer] can be restarted freely.
 */
class SyncedRenderer(val doFrame: (frameTimeNanos: Long) -> Unit) {

    private var callback: (Long) -> Unit = {}

    fun start() {
        callback = {
            doFrame(it)
            Choreographer.getInstance().postFrameCallback(callback)
        }
        Choreographer.getInstance().postFrameCallback(callback)
    }

    fun stop() {
        Choreographer.getInstance().removeFrameCallback(callback)
        callback = {}
    }
}

用法:


val renderer = SyncedRenderer { frameTimeNanos: Long ->
    // My code here will execute on main thread every frame
}

// Example when dragging something

override fun onStartDrag() {
    renderer.start()
}

override fun onReleaseDrag() {
    renderer.stop()
}

我发现与仅使用固定速率Timer并以每帧刷新速率运行代码相比,它的性能仅高一点。

但是,通过此实现,您无需在背景线程上运行任何代码,因此在修改post时无需调用任何类型的View或它的相关方法。

更重要的是,尽管没有执行多余的执行工作,所以与使用硬编码刷新率计时器相比,这对于更平滑的滚动和动画制作非常有用。

希望这对某人有帮助:)