Android - 从计时器线程更新位图

Dav*_*rra 14 multithreading android opengl-es bitmap imageview

我有一个由一个带有ImageView的布局组成的Android项目.

public class MainActivity extends AppCompatActivity {

    /* original and stretched sized bitmaps */
    private Bitmap bitmapOriginal;
    private Bitmap bitmapStretched;

    /* the only view */
    private ImageView iv;

    ....
}
Run Code Online (Sandbox Code Playgroud)

此ImageView由此runnable函数更新

    runnable = new Runnable() {
        @Override
        public void run() {
            iv.setImageBitmap(bitmapStretched);
        }
    };
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

绘制一些帧后,应用程序崩溃并显示以下消息.

A/OpenGLRenderer: Task is already in the queue!
Run Code Online (Sandbox Code Playgroud)

我想这是因为渲染器没有完成呈现ImageView的前一帧并且生气.

如果我删除runOnUiThread(runnable);问题消失(显然)

怎么能避免这个?如何将我的应用程序与openGL渲染器同步?

我还试图扩展ImageView并在画布上绘制位图到onDraw函数,但我得到了相同的结果

urv*_*l50 6

我猜你正在尝试创建bitmapOriginal ouside线程.因此,当编译器在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);
}
Run Code Online (Sandbox Code Playgroud)


Jsc*_*ols 5

使绘图逻辑与设备的帧速率同步的正确方法是使用SurfaceView而不是ImageView.您应该创建一个尝试尽可能快地渲染帧的渲染线程,而不是使用您自己的计时器将帧推送到View.当您拨打电话时surfaceHolder.lockCanvas(),Android系统将自动阻止,直到呈现帧为止.使用时解锁画布时unlockCanvasAndPost(),系统会将缓冲区绘制到屏幕上.

有关详细信息,请参阅https://developer.android.com/guide/topics/graphics/2d-graphics.html#on-surfaceview.希望这可以帮助!


Dav*_*rra 4

问题与位图本身完全无关......

这是实时时钟信号扰乱了 Android RenderThread。

进一步解释在这里:

Android和JNI实时时钟