Android: actualiza el mapa de bits del hilo del temporizador

Tengo un proyecto de Android compuesto por un solo Layout con un ImageView.

public class MainActivity extends AppCompatActivity { /* original and stretched sized bitmaps */ private Bitmap bitmapOriginal; private Bitmap bitmapStretched; /* the only view */ private ImageView iv; .... } 

Este ImageView es actualizado por esta función ejecutable

  runnable = new Runnable() { @Override public void run() { iv.setImageBitmap(bitmapStretched); } }; 

Y el runnable es ejecutado por una función temporizada JNI, que se ejecuta en un hilo de fondo, que la llaman 60 veces por segundo.

 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); } 

Después de trazar un marco, la aplicación se bloquea con el siguiente mensaje.

 A/OpenGLRenderer: Task is already in the queue! 

Supongo que esto es porque el renderizador no terminó de procesar completamente el marco anterior de ImageView y se enoja.

Si quito runOnUiThread(runnable); El problema desaparece (obviamente)

¿Cómo se puede evitar esto? ¿Cómo puedo sincronizar mi aplicación con el renderizador openGL?

También traté de ampliar ImageView y dibujar el mapa de bits en lienzo en la función onDraw, pero tengo el mismo resultado

6 Solutions collect form web for “Android: actualiza el mapa de bits del hilo del temporizador”

Supongo que estás intentando crear bitmapOriginal fuera del hilo. Por lo tanto, cuando el compilador está intentando llamar de nuevo después de 60 segundos, obtiene los mismos objetos y no pudo identificar la tarea. Yo sugeriría mejor como abajo.

  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); } 

La forma correcta de sincronizar la lógica de dibujo con la velocidad de fotogramas del dispositivo es utilizar un SurfaceView en lugar de un ImageView. En lugar de empujar los marcos a la vista con su propio temporizador, debe crear un hilo de renderizado que intente hacer marcos lo más rápido posible. Cuando llame a surfaceHolder.lockCanvas() , el sistema Android bloqueará automáticamente hasta que sea el momento de procesar el marco. Cuando desbloquea el lienzo utilizando unlockCanvasAndPost() , el sistema dibujará el búfer en la pantalla.

Consulte https://developer.android.com/guide/topics/graphics/2d-graphics.html#on-surfaceview para obtener más información. ¡Espero que esto ayude!

El problema era totalmente ajeno al mapa de bits …

Era la señal de reloj en tiempo real que se mezclaba con Android RenderThread.

Más explicaciones aquí:

Android y JNI reloj en tiempo real

Proporcionar aquí los propósitos de uso de este método para la prestación? ¿Qué quieres hacer ?, hay gran funcionalidad de animación en el motor de Android, puede ser esta tarea se puede hacer con esta animación.

Uno más si usted usará códigos como su batería del teléfono funcionará a cero coz muy rápido esto cargará la CPU / gpu al máximo.

En cualquier caso – intenta colocar bloques de ejecutar la tarea, establecer bool taskRun = true en el inicio y comprobar if (!taskRun){ taskRun = true; //here start your task..} if (!taskRun){ taskRun = true; //here start your task..} y en ui hilo después de actualizar ui puedes cambiar a taskRun = false; Utilizando esto, puede omitir algunos fotogramas, pero no debe bloquearse.

El problema es que el Handler del hilo principal es mantener una referencia a su Runnable . Cuando desee ejecutar su Runnable por segunda vez, el antiguo Runnable ya está en Message Queue , por lo tanto, Task is already in the queue mensaje de Task is already in the queue . Si crea un Runnable cada vez que desea ejecutar el Runnable como en el código de abajo, creo que el problema se resolverá.

 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(new Runnable() { @Override public void run() { iv.setImageBitmap(bitmapStretched); } }); } 

Creo que tienes razón con razón, porque no puedes estar seguro, de que Android reproduce imágenes en 60 FPS. Y sí, creo que sólo necesita sincronizar la devolución de llamada nativa de mapa de bits con Android Render. Así que, vamos a empezar.

Prefiero usar Bloqueo desde la pila de concurrencia Java. Porque ves, cuando bloqueas el objeto y cuando desbloqueas. En caso de utilizar volátiles (por ejemplo, seguro que también hay restricciones de referencia) en el objeto Bitmap, debe comprobar el bloqueo de este objeto en lugares muy, donde se utiliza Bitmap.

También creo que deberías usar Lock desde ESTE EJEMPLO (para desbloquear el objeto Lock de cualquier otro hilo). Así que, aquí está el ejemplo. El siguiente ejemplo funcionará correctamente. Sólo no se olvide de la eliminación del contexto y detener la tarea:

 public class MainActivity extends AppCompatActivity { /* Initialize lock (avoid lazy init, with your methods) */ private ReentrantLock lock = new ReentrantLock(); ............ private runnableDrawImage = new Runnable() { @Override public void run() { iv.setImageBitmap(bitmapStretched); lock.unlock(); } }; .......... public void jniTemporizedCallback(int buf[]) { /* synchronize by locking state*/ lock.lock(); bitmapOriginal = Bitmap.createBitmap(///) bitmapOriginal.setPixels(buf, 0, origWidth, 0, 0, origWidth, origHeight); bitmapStretched = Bitmap.createScaledBitmap(bitmapOriginal, width, height,false); MainActivity.this.runOnUiThread(runnableDrawImage); } } 
  • ¿Emulador de BlueStacks para Linux?
  • Zero-copia de procesamiento de la cámara y la prestación de tuberías en Android
  • Android OpenGL textura de origen no local utilizando Rajawali3D?
  • Android OpenGL gameloop fuera de OnFrame
  • OpenGL y 9 trazos desmontables
  • Error al intentar obtener Alraedy creado Surface y recibir EGLNativeWindowType ya conectado a otro error de API
  • Cargando texturas en una aplicación de Android OpenGL ES
  • ¿Dónde se especifica cómo OpenGL ES 2.0 representa los valores de textura flotante en el fragmento shader?
  • Android OpenGL ES 2.0: El modelo de cubo no sólo está distorsionado (la perspectiva es incorrecta?), Sino también las caras se cargan incorrectamente (los vértices no son correctos?)
  • ¿Hay algún dispositivo Android con un tamaño de pantalla mayor que GL_MAX_TEXTURE_SIZE?
  • Alejarse en OpenGL en android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.