我需要在Android应用程序中运行一个复杂的自定义动画。为此,我编写了一个需要反复调用的函数,并使用当前时间戳来计算View元素在屏幕上的位置、颜色、阴影等。
我可以使用一大堆不同的方法来实现这个名为的函数
- 带活动的标准Java多线程.runOnUIThread
- "尾部递归"View.post调用
- 计时器
- 异步任务
- 天知道还有什么…:)
在我当前的实现中,我只是通过runOnUIThread从一个单独的线程调用我的动画函数。虽然它有效,但这似乎不是一个好主意,因为它可能会以比屏幕刷新所需的处理速度更快的速度向事件队列中大量发送消息。。。
几个小时前,我在iOS上发布了一个类似的问题,@IanMacDonald为我提供了一个惊人的答案,它允许在每次屏幕刷新前调用我的函数一次,并使动画非常流畅。我在安卓系统中是否可以做类似的事情,即每次屏幕即将刷新时都让它调用我的功能?
如果可能的话,我想使用一种尽可能向后兼容的方法,最好是API 7或更低。。。
我做了更多的阅读,目前的首选方法似乎是使用Choreographer的postFrameCallback方法。遗憾的是,Choreographer只是在API 16中添加的,这对我的使用来说有点太严格了。
这里有一种方法可以通过"递归"View.postDelayed调用(即Runnable将为自己重新发布View.postDelayed)来实现,延迟从Display.getRefreshRate:计算
import android.app.Activity;
import android.view.Display;
import android.view.View;
public abstract class DisplayRefreshTimer implements Runnable {
public DisplayRefreshTimer(final View view) {
Activity activity = (Activity) view.getContext();
Display display = activity.getWindowManager().getDefaultDisplay();
final int delay = (int) (1000 / display.getRefreshRate());
view.postDelayed(new Runnable() {
@Override
public void run() {
view.postDelayed(this, delay);
DisplayRefreshTimer.this.run();
}
}, delay);
}
}
要使用它,只需对其进行子类化,覆盖run()
并实例化,将其传递给您当前的视图:
new DisplayRefreshTimer(currentView) {
@Override
public void run() {
// Do your magic here...
}
};
如果你的目标是API 17+,你可以使用View.getDisplay而不是通过活动,但你也可以像上面提到的那样查看Choreographer。
请不要让这个初步答案阻止你发布其他想法。如果还有更好的解决方案,我也不会感到惊讶。也许在OpenGL框架中?乍一看,我在那里什么也找不到,但我也会继续找