我得到了一个由单个Layout和ImageView组成的Android项目。
public class MainActivity extends AppCompatActivity {
/* original and stretched sized bitmaps */
private Bitmap bitmapOriginal;
private Bitmap bitmapStretched;
/* the only view */
private ImageView iv;
....
}
此ImageView由此可运行函数更新
runnable = new Runnable() {
@Override
public void run() {
iv.setImageBitmap(bitmapStretched);
}
};
runnable由一个临时的JNI函数运行,在后台线程上运行,每秒调用它60次。
public void jniTemporizedCallback(int buf[]) {
/* set data to original sized bitmap */
bitmapOriginal.setPixels(buf, 0, origWidth, 0, 0, origWidth, origHeight);
/* calculate the stretched one */
bitmapStretched = Bitmap.createScaledBitmap(bitmapOriginal, width, height, false);
/* tell the main thread to update the image view */
runOnUiThread(runnable);
}
绘制某些帧后,应用程序会崩溃并显示以下消息。
A/OpenGLRenderer: Task is already in the queue!
我想这是因为渲染器没有完成对ImageView的前一帧的完全渲染,因此会生气。
如果我删除runOnUiThread(可运行)代码>问题消失(显然)
如何避免这种情况?如何将应用程序与openGL渲染器同步?
我还尝试扩展 ImageView 并将画布上的位图绘制到 onDraw 函数中,但我得到了相同的结果
我猜你正在尝试在线程之外创建bitmapOriginal。因此,当编译器试图在60秒后再次调用时,它得到相同的对象,无法识别任务。我建议如下。
public void jniTemporizedCallback(int buf[]) {
// Initialize
bitmapOriginal = Bitmap.createBitmap(///)
/* set data to original sized bitmap */
bitmapOriginal.setPixels(buf, 0, origWidth, 0, 0, origWidth, origHeight);
/* calculate the stretched one */
bitmapStretched = Bitmap.createScaledBitmap(bitmapOriginal, width, height,false);
/* tell the main thread to update the image view */
runOnUiThread(runnable);
}
将绘制逻辑与设备的帧速率同步的正确方法是使用SurfaceView而不是ImageView。您应该创建一个渲染线程,尝试尽可能快地渲染帧,而不是使用您自己的计时器将帧推送到视图。当你调用< code > surface holder . lock canvas()时,Android系统会自动阻塞,直到该渲染帧的时候。当您使用< code > unlockCanvasAndPost()解锁画布时,系统会将缓冲区绘制到屏幕上。
如需更多资讯,请参阅https://developer . Android . com/guide/topics/graphics/2d-graphics . html # on-surface view。希望这有所帮助!
问题与位图本身完全无关。。。。
是实时时钟信号扰乱了Android RenderThread。
此处进一步解释:
Android和JNI实时时钟