¿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?

Respuestas:


163

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

Si.


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.


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í .


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.


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)

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.