web-dev-qa-db-fra.com

Les radiodiqueurs de Android sont-ils lancés dans un nouveau fil?

Si j'ai une classe intérieure qui s'étend BroadcastReceiver dans ma catégorie Service, devrais-je me soucier de la synchronisation, lorsque la classe BroadcastReceiver lit lit/écrit aux objets du Service classer? Ou de la mettre d'une autre manière: sont BroadacstReceiver 's onReceive() méthodes ont commencé dans un fil supplémentaire?

38
Flow

La méthode Onreceive () est toujours appelée sur le thread principal (qui est également appelé "thread d'interface utilisateur"), à moins que vous ne le demandiez qu'il soit planifié sur un thread différent à l'aide de la variante RegisterRecefeiver ():

Context.registerReceiver(BroadcastReceiver receiver,
                         IntentFilter filter,
                         String broadcastPermission,
                         Handler scheduler)
40
Nick Pelly

Les radiodiqueurs de Android sont-ils lancés dans un nouveau fil?

Habituellement mais pas toujours, tout dépend de la façon dont vous l'enregistrez.

Si vous enregistrez votre BroadcastReceiver utilisant:

registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

Il fonctionnera dans le Fil d'activité principale (filetage de l'interface utilisateur).

Si vous enregistrez votre BroadcastReceiver à l'aide d'un Handler exécuté sur un autre fil:

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

Il fonctionnera dans le contexte de votre Handler

Par exemple:

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

Détails ici & ICI .

21
Caner

la méthode onreceive () est appelée sur le thread principal. Donc, au cas où tout votre accès à la classe de service est effectué à partir du fil principal, vous n'avez besoin de synchronisation.

18
Stephan

De plus, vous pouvez spécifier l'attribut "Android: Process" Element d'élément de récepteur dans l'androidManifest.xml. Voir ICI . De cette façon, vous pouvez spécifier que le récepteur fonctionne comme un processus distinct et n'est pas attaché au fil principal de l'UI.

2
stoker

Les récepteurs de diffusion Android sont par défaut Démarrer dans le fil de l'interface graphique (fil principal) si vous utilisez RegisterReceiver(broadcastReceiver, intentFilter).

Mais il peut être exécuté dans un fil de travail comme suit;

Lorsque vous utilisez une poignée, assurez-vous de quitter le thread après la discrimination du BroadcastEver. Sinon, les fuites de descripteur de fichier (FD) se produisent sous du niveau Linux et enfin que l'application est écrasée si elle continue à enregistrer/désenregistrer.

unregisterReceiver (...);

Puis looper.quit (); Ou looper.Qui®Any ();

private Handler broadcastReceiverHandler = null;
private HandlerThread broadcastReceiverThread = null;
private Looper broadcastReceiverThreadLooper = null;

private BroadcastReceiver broadcastReceiverReadScans = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {

    }
}

private void registerForIntents() {
    broadcastReceiverThread = new HandlerThread("THREAD_NAME");//Create a thread for BroadcastReceiver
    broadcastReceiverThread.start();

    broadcastReceiverThreadLooper = broadcastReceiverThread.getLooper();
    broadcastReceiverHandler = new Handler(broadcastReceiverThreadLooper);

    IntentFilter filterScanReads = new IntentFilter();
    filterScanReads.addAction("ACTION_SCAN_READ");
    filterScanReads.addCategory("CATEGORY_SCAN");

    context.registerReceiver(broadcastReceiverReadScans, filterScanReads, null, broadcastReceiverHandler);
}

private void unregisterIntents() {
    context.unregisterReceiver(broadcastReceiverReadScans);
    broadcastReceiverThreadLooper.quit();//Don't forget
}
0
Samantha