example - httphandler android
El mejor uso de HandlerThread sobre otras clases similares (2)
Estoy tratando de entender el mejor caso de uso de HandlerThread
.
Según la definición:
"Clase útil para iniciar un nuevo hilo que tiene un looper. El looper puede usarse para crear clases de controlador. Tenga en cuenta que start () todavía debe ser llamado".
Puedo estar equivocado, pero puedo lograr una funcionalidad similar al utilizar un Thread
, un Looper
y un Handler
. Entonces, ¿cuándo debería usar HandlerThread
? Un ejemplo sería realmente útil.
Aquí hay un ejemplo de la vida real donde HandlerThread vuelve práctico. Cuando se registra para marcos de vista previa de cámara, los recibe en la devolución de llamada onPreviewFrame()
. La documentation explica que esta devolución de llamada se invoca en el evento de apertura de subproceso (int) desde .
Por lo general, esto significa que la devolución de llamada se invocará en el hilo principal (UI). Por lo tanto, la tarea de lidiar con las enormes matrices de píxeles puede atascarse cuando se abren los menús, 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 una post(Runnable)
, no es necesario implementar Handler.Callback
).
Tenga en cuenta que todos los demás trabajos con la cámara se pueden realizar como de costumbre, no es necesario delegar Camera.startPreview()
o Camera.setPreviewCallback()
en HandlerThread. Para estar seguro, espero que se Camera.open(int)
real antes de continuar en el hilo principal (o el hilo que se usó para llamar a Camera.open()
antes del cambio).
Entonces, si comienzas 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 extráigalo como está 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 toda la comunicación entre hilos de notify () - wait () no es necesaria si no accede a mCamera en el código original inmediatamente después de abrirlo.
Actualización: Aquí se aplica el mismo enfoque al acelerómetro: Sensor accróner en hilo separado
Aquí hay un enlace al código fuente para HandlerThread y Looper .
Si miras a los dos, verás que HandlerThread
es exactamente lo que dice que es, una forma conveniente de iniciar un Thread
que tiene un Looper
. ¿Por qué existe esto? Porque los hilos, de forma predeterminada, no tienen un bucle de mensaje . HandlerThread
es una forma sencilla de crear uno que sí lo haga. ¿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 tareas ejecutables enviadas y, adivina qué, las ejecuta. ¿Por qué es esto necesario? Le permite desacoplar la ejecución de la tarea de su sustancia real . ¿Cuándo usarías esto? Supongamos que tiene una situación que requiere la ejecución de múltiples tareas al mismo tiempo. Puede elegir, usando un Executor
, ejecutarlos todos en un solo hilo para que se ejecuten seriamente. O puede usar un grupo de subprocesos fijos para que algunos, pero no todos, se ejecuten al mismo tiempo. En cualquier caso, la sustancia de la tarea, es decir, lo que realmente está haciendo, está separada de la manera en que se está ejecutando.