Mejor uso de HandlerThread sobre otras clases similares

Estoy tratando de entender el mejor caso de uso de HandlerThread .

Según definición:

"Clase práctica para iniciar un nuevo subproceso que tiene un looper.El looper puede utilizarse para crear clases de manejadores.Nota que start () debe seguir siendo llamado".

Puedo estar equivocado, pero la funcionalidad similar que puedo lograr mediante el uso de un Thread , Looper y Handler . Entonces, ¿cuándo debo usar HandlerThread ? Un ejemplo sería muy útil.

Aquí hay un ejemplo de la vida real donde HandlerThread se convierte en práctico. Cuando se registra en los fotogramas de previsualización de la cámara, los recibe en la onPreviewFrame() devolución de llamada onPreviewFrame() . La documentación explica que se invoca esta devolución de llamada en el segmento de evento abierto (int) desde el que se llamó .

Normalmente, esto significa que la devolución de llamada se invocará en el subproceso principal (UI). Por lo tanto, la tarea de tratar con las matrices de píxeles enormes puede quedar atascado cuando los menús se abren, las animaciones se animan, o incluso si las estadísticas se imprimen en la pantalla.

La solución fácil es crear un new HandlerThread() y delegar Camera.open() a este hilo (lo hice a través de post(Runnable) , no es necesario implementar Handler.Callback ).

Tenga en cuenta que todos los demás trabajos con la cámara se pueden hacer como de costumbre, no es necesario delegar Camera.startPreview() o Camera.setPreviewCallback() en HandlerThread. Para estar en el lado seguro, espero que el Camera.open(int) real Camera.open(int) para completar antes de continuar en el hilo principal (o cualquier hilo se utilizó para llamar a Camera.open() antes del cambio).


Por lo tanto, si empieza con el código

 try { mCamera = Camera.open(1); } catch (RuntimeException e) { Log.e(LOG_TAG, "failed to open front camera"); } // some code that uses mCamera immediately 

Primero extraerlo como es en un método privado:

 private void oldOpenCamera() { try { mCamera = Camera.open(1); } catch (RuntimeException e) { Log.e(LOG_TAG, "failed to open front camera"); } } 

Y en lugar de llamar a oldOpenCamera() simplemente use newOpencamera() :

 private void newOpenCamera() { if (mThread == null) { mThread = new CameraHandlerThread(); } synchronized (mThread) { mThread.openCamera(); } } private CameraHandlerThread mThread = null; private static class CameraHandlerThread extends HandlerThread { Handler mHandler = null; CameraHandlerThread() { super("CameraHandlerThread"); start(); mHandler = new Handler(getLooper()); } synchronized void notifyCameraOpened() { notify(); } void openCamera() { mHandler.post(new Runnable() { @Override public void run() { oldOpenCamera(); notifyCameraOpened(); } }); try { wait(); } catch (InterruptedException e) { Log.w(LOG_TAG, "wait was interrupted"); } } } 

Tenga en cuenta que la notificación entera de notification ()wait () entre hilos no es necesaria si no tiene acceso a mCamera en el código original inmediatamente después de abrirlo.

Actualización: Aquí se aplica el mismo enfoque al acelerómetro: Sensor de acerómetro en hilo separado

Aquí hay un enlace al código fuente de HandlerThread y Looper .

Si nos fijamos en los dos verá que un HandlerThread es exactamente lo que dice que es – una forma conveniente de iniciar un Thread que tiene un Looper . ¿Por qué existe esto? Debido a que los subprocesos, por defecto, no tienen un bucle de mensaje . El HandlerThread es sólo una manera fácil de crear uno que lo hace. ¿Podría duplicar esta función con Handler , Thread y Looper – a juzgar por el código fuente – la respuesta es sí.

Un Executor es diferente. Un Executor toma las tareas ejecutables enviadas y – adivina qué – las ejecuta. ¿Por qué es necesario? Le permite desacoplar la ejecución de la tarea de su sustancia real . ¿Cuándo usarías esto? Digamos que tenías una situación que requería la ejecución de varias tareas al mismo tiempo. Usted puede elegir, usando un Executor , para ejecutarlos todos en un solo hilo para que se ejecuten en serie. O puede utilizar un grupo de hilos fijo para que algunos, pero no todos se ejecuten al mismo tiempo. En cualquier caso, la sustancia de la tarea – es decir, lo que está haciendo en realidad – es independiente de la forma en que se está ejecutando.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.