BroadcastReceiver.onReceive viene sempre eseguito nel thread dell'interfaccia utente?


117

Nella mia App, creo un custom BroadcastReceivere lo registro manualmente nel mio contesto tramite Context.registerReceiver. Ho anche un messaggio AsyncTaskche invia notifier-Intents tramite Context.sendBroadcast. Gli intenti vengono inviati da un thread di lavoro non dell'interfaccia utente, ma sembra che BroadcastReceiver.onReceive(che riceve detti intenti) venga sempre eseguito nel thread dell'interfaccia utente (il che è positivo per me). È garantito o non dovrei fare affidamento su quello?

Risposte:


163

BroadcastReceiver.onReceive viene sempre eseguito nel thread dell'interfaccia utente?

Sì.


9
è documentato da qualche parte?
Hannes Struß

15
@hannes: il 99,44% delle volte, se Android chiama il tuo codice, si trova nel thread dell'applicazione principale. Tutti i metodi del ciclo di vita (ad esempio, onCreate(), onReceive()) sono chiamati thread dell'applicazione principale. Ed è documentato nei documenti per onReceive(): goo.gl/8kPuH
CommonsWare

2
ok, sto solo interpretando "è normalmente chiamato nel thread principale" dai documenti come "sempre" e spero che le cose non si rompano ;-) Grazie!
Hannes Struß

4
@Hannes Struß: Non so perché hanno coperto la loro lingua con "normalmente". Non riesco a pensare a nessun caso in cui onReceive()viene chiamato su un thread diverso dal thread dell'applicazione principale ("UI").
CommonsWare

31
@CommonsWare: "Non riesco a pensare a nessun caso in cui onReceive () viene chiamato su un thread diverso dal thread dell'applicazione principale (" UI ")" - il caso è se BroadcastReceiver è registrato utilizzando registerReceiver (BroadcastReceiver, IntentFilter, String, Handler), l'argomento del gestore non è null e fa riferimento a un gestore creato in un thread diverso dal thread dell'applicazione principale.
Jules

76

Poiché registri dinamicamente il destinatario, puoi specificare che un altro thread (diverso dal thread dell'interfaccia utente) gestisce il file onReceive(). Questa operazione viene eseguita tramite il parametro Handler di registerReceiver () .

Detto questo, se non hai specificato un altro gestore, verrà sempre gestito sul thread dell'interfaccia utente.


Sì. Sembra che la tua capacità di cambiarlo tramite il parametro Handler sia il motivo per cui hanno "protetto" la loro lingua nei documenti.
Andrew Mackenzie

64

BroadcastReceiver.onReceive viene sempre eseguito nel thread dell'interfaccia utente?

Di solito, tutto dipende da come lo registri.

Se registri il tuo BroadcastReceiverutilizzo:

registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

Verrà eseguito nel thread di attività principale (noto anche come thread dell'interfaccia utente) .

Se ti registri BroadcastReceiverutilizzando una Handler esecuzione valida su un thread diverso :

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

Funzionerà nel contesto del tuo Handler

Per esempio:

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

Dettagli qui e qui .


3
Dopo aver esaminato questa opzione per un po ', alla fine mi sono reso conto che LocalBroadcastManager non supporta l'utilizzo di un gestore personalizzato. Quindi, se stai usando un LBM invece di un contesto per registrare il tuo ricevitore, questo approccio non si applica. Sfortunatamente, in quel caso sembra che la nostra unica opzione rimasta sia quella di utilizzare un servizio per andare in background ed evitare gli ANR che i ricevitori si attivano dopo 10 secondi di inattività.
gMale

9

Poiché le risposte precedenti correttamente indicate onReceiveverranno eseguite sul thread con cui è registrato se registerReceiver()viene chiamato il sapore di quello accetta un gestore, altrimenti sul thread principale.

Tranne se il destinatario è registrato con LocalBroadcastManagere la trasmissione è tramite sendBroadcastSync- dove apparentemente verrà eseguita sul thread che chiamasendBroadcastSync.


Non sono d'accordo con la parte and the broadcast is via sendBroadcastSync. Quando usiamo LocalBroadcastManagerper registrare il ricevitore, deve essere chiamato dal thread principale se use sendBroadcastSynco sendBroadcast. Quindi la chiave è quella di usare LocalBroadcastManagerper registrarsi. Ho ragione?
kidoher

@kidoher: Hai seguito i link al codice qui: stackoverflow.com/q/20820244/281545 ?
Mr_and_Mrs_D

0

SÌ Context.registerReceiver (ricevitore BroadcastReceiver, filtro IntentFilter, String broadcastPermission, Handler scheduler)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.