OpenGL ES线程中的Android计时不是单调的

时间:2014-05-01 15:50:00

标签: android timer opengl-es-2.0

我在Android应用中测量循环动画/粒子/等的时间间隔。应用程序是一个动态壁纸,因此它不会阻止系统缩减时钟以节省电力。 因此,测量最后帧之间的时间间隔的所有方法都不能测量单调时间 - 我体验的动画不一致地减慢和加速。

我已经使用了所有可能的方法来检索系统时间 - 所有这些方法都不是单调的(即使SystemClock.elapsedRealtime()System.nanoTime() 保证是单调的但是没有不是)。

如果我在屏幕上按住手指以防止省电,则所有动画都会流畅。 这个问题在Nexus10上非常引人注目,在Nexus7 1st gen上略显引人注目,在Nexus4上它根本不存在。

以下是衡量时间的代码摘录:

public void onDrawFrame(GL10 glUnused) {
    // calculate timers for animations based on difference between lastFrameTime and SystemClock.elapsedRealtime()
    ...
    // save last timestamp for this frame
    lastFrameTime = SystemClock.elapsedRealtime();
}

1 个答案:

答案 0 :(得分:2)

根据代码大纲对我认为你正在做的事情进行一点扩展,伪代码中的onDrawFrame()方法如下所示:

deltaTime = SystemClock.elapsedRealtime() - lastFrameTrime
// point 1, see text below
update animation based on deltaTime
draw frame
// point 2, see text below
lastFrameTime = SystemClock.elapsedRealtime()

此序列的问题在于您从总动画时间中丢失了第1点和第2点之间的时间。您需要确保所有deltaTime值的总和(即应用于动画的时间)涵盖了动画的整个挂钟时间。使用您使用的逻辑,情况并非如此。您只需将一次通话的结束之间的时间加到下次通话的开始之间。您没有考虑执行该方法所需的时间,这可能很重要。

这可以通过序列的微小变化来解决:

currentTime = SystemClock.elapsedRealtime()
deltaTime = currentTime - lastFrameTime
lastFrameTime = currentTime
update animation based on deltaTime
draw frame

关键是你每帧只能调用一次elapsedRealtime()