¿BroadcastReceiver.onReceive siempre se ejecuta en el hilo de la interfaz de usuario?

117

En mi aplicación, creo un personalizado BroadcastReceivery lo registro en mi contexto manualmente a través de Context.registerReceiver. También tengo un AsyncTaskque envía notifier-Intents a través de Context.sendBroadcast. Las intenciones se envían desde un hilo de trabajo que no es de la interfaz de usuario, pero parece que BroadcastReceiver.onReceive(que recibe dichas intenciones) siempre se ejecuta en el hilo de la interfaz de usuario (lo cual es bueno para mí). ¿Está esto garantizado o no debo confiar en eso?

Hannes Struß
fuente

Respuestas:

163

¿BroadcastReceiver.onReceive siempre se ejecuta en el hilo de la interfaz de usuario?

Si.

CommonsWare
fuente
9
¿Está esto documentado en alguna parte?
Hannes Struß
15
@hannes: el 99,44% de las veces, si Android llama a su código, está en el hilo principal de la aplicación. Todos los métodos de ciclo de vida (por ejemplo, onCreate(), onReceive()) se denominan en el hilo principal de la aplicación. Y está documentado en los documentos para onReceive(): goo.gl/8kPuH
CommonsWare
2
ok, solo estoy interpretando el "normalmente se llama dentro del hilo principal" de los documentos como "siempre" y espero que las cosas no se rompan ;-) ¡Gracias!
Hannes Struß
4
@Hannes Struß: No sé por qué rodearon su lenguaje con "normalmente". No puedo pensar en ningún caso en el que onReceive()se llame a un hilo que no sea el hilo de la aplicación principal ("UI").
CommonsWare
31
@CommonsWare: "No puedo pensar en ningún caso en el que se llame a onReceive () en un hilo que no sea el hilo de la aplicación principal (" UI ")" - el caso es si el BroadcastReceiver está registrado usando registerReceiver (BroadcastReceiver, IntentFilter, String, Handler), el argumento del controlador no es nulo y se refiere a un controlador creado en un hilo distinto del hilo principal de la aplicación.
Jules
76

Dado que registra dinámicamente el receptor, puede especificar que otro hilo (que no sea el hilo de la interfaz de usuario) maneje el onReceive(). Esto se hace a través del parámetro Handler de registerReceiver () .

Dicho esto, si no especificó otro controlador, siempre se manejará en el hilo de la interfaz de usuario.

TommyTh
fuente
Si. Parece que su capacidad para cambiarlo a través del parámetro Handler es la razón por la que "cubrieron" su idioma en los documentos.
Andrew Mackenzie
64

¿BroadcastReceiver.onReceive siempre se ejecuta en el hilo de la interfaz de usuario?

Por lo general, todo depende de cómo lo registre.

Si registra su BroadcastReceiveruso:

registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

Se ejecutará en el hilo de actividad principal (también conocido como hilo de UI) .

Si registra su BroadcastReceiveruso de una Handler ejecución válida en un hilo diferente :

registerReceiver (BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)

Se ejecutará en el contexto de su Handler

Por ejemplo:

HandlerThread handlerThread = new HandlerThread("ht");
handlerThread.start();
Looper looper = handlerThread.getLooper();
Handler handler = new Handler(looper);
context.registerReceiver(receiver, filter, null, handler); // Will not run on main thread

Detalles aquí y aquí .

Caner
fuente
3
Después de mirar esta opción por un tiempo, finalmente me di cuenta de que LocalBroadcastManager no admite el uso de un controlador personalizado. Entonces, si está utilizando un LBM en lugar de un contexto para registrar su receptor, este enfoque no se aplica. Desafortunadamente, en ese caso, parece que nuestra única opción que nos queda es usar un Servicio para pasar a segundo plano y evitar los ANR que los receptores activan después de 10 segundos de inactividad.
gMale
9

Como se indicaron correctamente las respuestas anteriores, onReceivese ejecutará en el hilo con el que está registrado si registerReceiver()se llama al tipo de que acepta un controlador; de lo contrario, en el hilo principal.

Excepto si el receptor está registrado con el LocalBroadcastManagery la transmisión es vía sendBroadcastSync, donde aparentemente se ejecutará en el hilo que llamasendBroadcastSync.

Mr_and_Mrs_D
fuente
No estoy de acuerdo con la parte and the broadcast is via sendBroadcastSync. Cuando usamos LocalBroadcastManagerpara registrar el receptor, debe ser llamado por el hilo principal, ya sea que use sendBroadcastSynco sendBroadcast. Entonces la clave es que use LocalBroadcastManagerpara registrarse. Estoy en lo cierto?
kidoher
@kidoher: ¿Seguiste los enlaces del código aquí: stackoverflow.com/q/20820244/281545 ?
Mr_and_Mrs_D
0

YES Context.registerReceiver (receptor BroadcastReceiver, filtro IntentFilter, String broadcastPermission, Handler planificador)

Akash
fuente