Android BroadcastReceiver ou simple méthode de rappel?

dans mes projets, j'utilise BroadcastReceiver comme rappel à partir d'un fil long (par ex. informer l'activité qu'un téléchargement a été terminé et envoyer des données de réponse d'un travailleur Thread afin que l'activité peut afficher le message approprié à l'utilisateur..). Pour utiliser BroadcastReceiver s je dois être prudent d'enregistrer et de désinscrire le récepteur de radiodiffusion chaque fois que je l'utilise et doivent également se soucier de ce que les messages à envoyer esspecialy quand je utilise cette méthode pour plus différentes actions (comme Télécharger, faire des appels webservices, etc..). Et aussi pour envoyer des objets personnalisés à travers L'intention de Broadcast je dois aussi faire les objets Parcelable .

contrairement à cette approche, j'ai vu aussi l'approche des méthodes de rappel qui semble être plus simple que la méthode que j'utilise. Les méthodes de Callback sont des méthodes simples D'implémentation de méthodes D'Interface qui peuvent être utilisées pour obtenir le même effet que le BroadcastRecaiver dans la messagerie app. Cette approche n'est pas il faut une implémentation Morcelable pour retourner des objets complexes et il n'utilise pas des clés comme BroadcastReceiver .. Je pense que la mauvaise partie est que je dois vérifier l'objet callback pour la valeur null avant de vouloir appeler une méthode callback.. et aussi pour m'assurer que j'exécute le code à partir de l'implémentation sur le thread D'UI pour pouvoir mettre à jour L'UI sans erreurs.

Ok, j'espère que vous avez compris ce que je voulais dire :).

maintenant, la question Est de savoir si vous pensez que le la méthode de rappel est meilleure (plus légère, plus propre, plus rapide..) que l'approche BroadcastReceiver lorsque sont utilisés juste à l'intérieur d'une seule application? (Notez que je n'utilise pas Android Service pour le travail de fond.. juste AsyncTask et Thread s)

Merci!

49
demandé sur Cata 2012-05-14 01:03:30

5 réponses

C'est une question très intéressante et j'ai rencontré le même problème. À mon avis, les deux mécanismes peuvent être utilisés dans leur ensemble et la bonne approche dépend de votre cas d'utilisation. Voici quelques points à prendre en compte avant de se décider.

L'Utilisation du mécanisme de rappel présente certains avantages, mais il y a aussi des limites:

PRO

  • Il est simple et facile à mettre en œuvre.
  • vous obtenez type-sécurité entre les composants qui interagissent les uns avec les autres.
  • Vous pouvez retourner des objets arbitraires.
  • il simplifie les tests car vous n'avez qu'à injecter un appel simulé (par exemple généré par mockito ou quelque chose de similaire) dans les tests unitaires.

CONTRA

  • vous devez passer au fil principal afin de faire des manipulations UI.
  • vous ne pouvez avoir une relation qu'à 1 contre 1. Une relation de 1 À n (Modèle de l'observateur) n'est pas réalisable sans autre travail. Dans ce cas, je préférerais le mécanisme Observer / Observable D'Android.
  • comme vous l'avez déjà dit, vous devez toujours vérifier pour null avant d'invoquer les fonctions de rappel si le rappel peut être facultatif.
  • si votre composant doit offrir une sorte D'API de service avec un service différent fonctions et vous ne voulez pas avoir une interface de callback avec seulement quelques fonctions génériques de callback, vous devez décider si vous fournissez une interface de callback spéciale pour chaque fonction de service ou si vous fournissez une interface de callback simple avec beaucoup de fonctions de callback. Dans le dernier cas, tous les clients de callback utilisés pour les appels de service vers votre API doivent implémenter l'interface de callback complète, bien que la majorité des corps de méthode soient vides. Vous pouvez contourner cela en implémenter un talon avec des corps vides et faire hériter votre client callback de ce talon, mais ce n'est pas possible si déjà hériter d'une autre classe de base. Peut-être que vous pouvez utiliser une sorte de rappel par procuration dynamique (voir http://developer.android.com/reference/java/lang/reflect/Proxy.html ), mais alors il devient vraiment complexe et je penserais à utiliser un autre mécanisme.
  • le client pour les appels de rappel doit être propagé à travers divers méthodes / composantes si elles ne sont pas directement accessibles à l'appelant du service.

Certains points concernant le BroadcastReceiver -approche:

PRO

  • vous réalisez un assemblage lâche entre vos composants.
  • vous pouvez avoir une relation 1-À-n (y compris 1-à-0).
  • la méthode onReceive() est toujours exécutée sur le filetage principal.
  • vous pouvez notifier des composants dans l'ensemble de votre application, de sorte que les composants communicants ne doivent pas" voir " l'un l'autre.

CONTRA

  • il s'agit d'une approche très générique, de sorte que la mise en commun et la suppression des données transportées par le Intent est une source d'erreur supplémentaire.
  • vous devez rendre les actions de votre Intent uniques (par exemple en préparant le nom du paquet) si vous voulez éliminer les corrélations avec d'autres applications, car leur but original est de faire des diffusions entre les applications.
  • vous devez gérer le BroadcastReceiver - enregistrement et non-enregistrement. Si vous voulez le faire d'une manière plus confortable, vous pouvez mettre en œuvre une annotation personnalisée pour annoter votre activité avec les actions qui doivent être enregistrées et mettre en œuvre une classe de base Activity qui fait l'enregistrement et le non-enregistrement avec IntentFilter s dans son onResume() REEE. onPause() méthodes.
  • comme vous l'avez déjà dit, les données qui est envoyé avec le Intent doit mettre en œuvre l'interface Parcelable , mais en outre, il ya une limite de taille stricte et il va causer des problèmes de performance si vous transportez une grande quantité de données avec votre Intent . Voir http://code.google.com/p/android/issues/detail?id=5878 pour une discussion à ce sujet. Donc, si vous voulez envoyer des images par exemple, vous devez les stocker temporaire dans un dépôt et envoyer un ID Ou URL correspondant pour accéder à l'image du récepteur de votre Intent qui la supprime du dépôt après utilisation. Cela entraîne d'autres problèmes s'il y a plusieurs récepteurs (quand l'image doit-elle être retirée du dépôt et qui doit le faire?).
  • si vous abusez de ce type de mécanisme de notification le flux de contrôle de votre application peut se cacher et lors du débogage vous finissez par dessiner des graphiques avec séquences de Intent s pour comprendre ce qui a déclenché une erreur spécifique ou pourquoi cette chaîne de notification est brisée à un moment donné.

à mon avis, même une application mobile devrait avoir une architecture basée sur au moins 2 couches: la couche UI-layer et la couche core (avec logique d'affaires, etc.). En général, les tâches de longue durée sont exécutées dans un propre thread (peut-être via AsyncTask ou HandlerThread si vous utilisez MessageQueue s) à l'intérieur de la couche principale et L'interface utilisateur devrait être mise à jour une fois cette tâche terminée. En général, avec les callbacks, vous réalisez un couplage serré entre vos composants, donc je préférerais utiliser cette approche seulement à l'intérieur d'une couche et pas pour la communication à travers les limites de la couche. Pour la diffusion de messages entre la couche UI et la couche core, j'utiliserais l'approche BroadcastReceiver qui vous permet de découpler votre couche UI de la couche logique.

78
répondu Andreas Klöber 2018-02-06 18:12:19

je ne vois pas ce que vous gagnez en utilisant BroadcastReceiver dans votre cas. Des Callbacks ou, mieux probablement, Handlers seraient le moyen de le faire. BroadcastReceiver est bon quand vous ne savez pas qui sont les abonnés.

6
répondu Alexander Kulyakhtin 2012-05-13 21:27:19

je vais juste ajouter une autre option aux autres grandes réponses que vous avez déjà reçues...

vous n'avez pas à créer un récepteur de radiodiffusion pour recevoir les intentions. Dans votre fichier de manifeste android, vous pouvez enregistrer n'importe quelle activité pour recevoir des intentions:

<activity android:name=".MyActivity">
        <intent-filter >
              <action android:name="intent.you.want.to.receive" /> 
              <category android:name="android.intent.category.DEFAULT" /> 
        </intent-filter>     
....
</activity>

puis outrepassez la méthode onNewIntent(Intent) dans votre activité pour la recevoir.

pour envoyer L'intention, utilisez la méthode Context.startActivity(Intent) . Vous voudrez probablement ajouter le FLAG_ACTIVITY_SINGLE_TOP marquez votre intention de sorte qu'il ne crée pas une nouvelle instance de votre activité si on est déjà en cours d'exécution.

EDIT: je viens de remarquer que vous exécutez dans une seule application. Par conséquent, un simple rappel est probablement préférable. La solution ci-dessus fonctionne dans une seule application, mais est plus appropriée pour différentes applications. Je vais laisser ça ici au cas où ça aiderait quelqu'un. Bonne chance!

3
répondu objbuilder 2012-05-16 16:29:21

les émetteurs de radiodiffusion devraient être utilisés si vous avez besoin d'envoyer des émissions à travers les applications tandis que les Callbacks (ou les Handlers comme suggéré par Alex) sont mieux à utiliser dans votre situation.

si vous voulez utiliser autre que ces deux, envisager d'utiliser Observateur (Interface incluse dans android) et délégué.

Pour déléguer veuillez considérer ce tant de poster .

2
répondu silwar 2018-02-06 18:14:03

pas sûr de ce que l'objectif est , mais si vous souhaitez garder la même idée de l'utilisation de intent et broadcastReceiver, et que vous voulez de meilleures performances et de la sécurité que la normale broadcastReceivers , vous pouvez essayer cette démo, disponible dans la bibliothèque de soutien android:

http://developer.android.com/resources/samples/Support4Demos/src/com/example/android/supportv4/content/LocalServiceBroadcaster.html

si non , vous pouvez utilisez toujours des asyncTask , de services , gestionnaires , etc...

1
répondu android developer 2012-05-16 20:30:11