54 votes

Android BroadcastReceiver ou méthode de rappel simple?

Dans mes projets, je suis en utilisant BroadcastReceivers comme un rappel à partir d'un long thread en cours d'exécution (par exemple. informer l'activité que le téléchargement est terminé et envoyer des données de réponse à partir d'un Travailleur Thread alors que l'activité peut afficher le message à l'utilisateur..). Pour utiliser BroadcastReceivers, je dois être prudent d'enregistrer et désenregistrer le récepteur de radiodiffusion à chaque fois que je l'utilise et aussi les soins de ce que les messages à envoyer esspecialy quand j'utilise cette méthode pour plus de différentes actions(comme le téléchargement, à la WebService appels, etc..). Et aussi pour envoyer des Objets personnalisés par l'intermédiaire de Diffusion de l'intention, j'ai besoin de faire l'objets d' Parcelable.

Contrairement à cette approche, j'ai vu aussi le rappel des méthodes d'approche qui semble être plus simple que la méthode que j'utilise. Les méthodes de rappel sont Interface simple les méthodes de mise en œuvre qui peut être utilisé pour obtenir le même effet comme le BroadcastRecaiver en application de messagerie. Cette approche n'a pas besoin de Parcelable mise en œuvre pour le retour des objets complexes et il n'utilise pas les touches BroadcastReceiver.. je pense que la mauvaise partie est que j'ai besoin de vérifier l'objet de rappel pour valeur null avant, je tiens à appeler une méthode de rappel.. et aussi pour m'assurer que je suis en cours d'exécution du code à partir de la mise en œuvre sur le thread de l'INTERFACE utilisateur afin que je puisse mettre à jour l'INTERFACE utilisateur sans erreurs.

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

Maintenant la question est, pensez-vous que la méthode de rappel est meilleur (plus léger, plus propre, plus rapide..) que l' BroadcastReceiver approche lorsqu'ils sont utilisés à l'intérieur d'une seule demande? (Notez que je ne suis pas en utilisant Android Service pour le travail de fond.. juste AsyncTask et Threads)

Merci!!!!

83voto

Andreas Klöber Points 2082

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 tout à fait et le droit de l'approche à utiliser dépend de votre cas d'utilisation. Voici quelques points à prendre en compte avant de se décider.

À l'aide de la fonction de rappel du mécanisme, a certains avantages, mais il y a aussi des limites:

PRO

  • Il est simple et facile à mettre en œuvre.
  • Vous obtenez le type de sécurité entre les composants qui interagissent les uns avec les autres.
  • Vous pouvez retourner des objets arbitraires.
  • Il simplifie les tests que vous avez seulement à injecter une maquette de rappel (par exemple généré par mockito ou quelque chose de similaire) dans les tests unitaires.

CONTRA

  • Vous devez l'activer pour le thread principal) afin de faire des manipulations de l'INTERFACE utilisateur.
  • Vous ne pouvez avoir qu'un 1-de-1 de la relation. 1-à-n (modèle observateur) n'est pas réalisable sans plus de travail. Dans ce cas, je préfère Android Observer / Observable mécanisme.
  • Comme vous l'avez déjà dit, vous devez toujours vérifier pour null avant d'appeler les fonctions de rappel si le rappel peut être facultatif.
  • Si votre composant devrait offrir une sorte de service de l'API avec les différentes fonctions de service et que vous ne voulez pas d'avoir une interface de rappel avec seulement quelques génériques des fonctions de rappel, vous devez décider si vous fournissez un spécial interface de rappel pour chaque fonction de service ou si vous fournissez une seule interface de rappel avec beaucoup de fonctions de rappel. Dans ce dernier cas de rappel tous les clients utilisés pour les appels de service à votre API doivent mettre en œuvre les compléter interface de rappel bien que la majorité de la méthode d'organes sera vide. Vous pouvez contourner ce problème en mettant en œuvre un talon avec des corps vides et faire de votre rappel client héritent de cette souche, 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 proxy dynamique de rappel (voir http://developer.android.com/reference/java/lang/reflect/Proxy.html), mais ensuite ça devient vraiment complexe, et je pense que d'utiliser un autre mécanisme.
  • Le client pour le rappel des appels doit être multiplié par le biais de diverses méthodes/composants si elle n'est pas directement accessible par l'appelant du service.

Certains points concernant l' BroadcastReceiver-approche:

PRO

  • Vous réaliser un couplage lâche entre vos composants.
  • Vous pouvez avoir un 1-à-n (y compris de 1 à 0).
  • L' onReceive() méthode est toujours exécuté sur le thread principal.
  • Vous pouvez vous informer des composants dans votre ensemble de l'application, de sorte que la communication des composants n'ont pas à "voir" à tour de rôle.

CONTRA

  • C'est une approche très générique, afin de mobiliser et unmarchalling de données transportées par l' Intent est une source d'erreur supplémentaire.
  • Vous avez pour faire de votre Intents'actions uniques (par exemple, en ajoutant le nom du paquet) si vous souhaitez éliminer les corrélations avec d'autres applications, comme leur but initial est de faire des émissions entre les applications.
  • A vous de gérer le BroadcastReceiver-l'inscription et la désinscription. Si vous voulez le faire d'une manière plus confortable, vous pouvez mettre en œuvre un d'annotations personnalisées pour annoter votre Activité avec les actions qui devraient être enregistrés et mettre en œuvre une base Activityclasse qui fait de l'inscription et de désinscription avec IntentFilters dans ses onResume() resp. onPause()méthodes.
  • Comme vous l'avez déjà dit, les données qui sont envoyées avec l' Intent a à mettre en œuvre l' Parcelable interface, mais en outre, il est une stricte limitation de taille et il va provoquer des problèmes de performances si vous le transport d'une grande quantité de données avec votre Intent. Voir http://code.google.com/p/android/issues/detail?id=5878 pour une discussion sur ce point. Donc, si vous voulez envoyer des images par exemple, vous devez les stocker temporaire dans un référentiel et d'envoyer un ID correspondant ou l'URL pour accéder à l'image du récepteur de votre Intent qui supprime le dépôt après utilisation. Cela conduit à d'autres problèmes, s'il y a plusieurs récepteurs (quand dois l'image soit retirée à partir du référentiel et qui doit le faire?).
  • Si vous abusez de ce type de mécanisme de notification le flux de contrôle de votre application peuvent être cachées et lors du débogage, en fin de tracer des graphiques avec des séquences d' Intents pour comprendre ce qui a déclenché une erreur spécifique ou pourquoi cette notification de la chaîne est rompu à un certain point.

À mon avis, même une application mobile doit disposer d'une architecture de base sur au moins 2 couches: l'INTERFACE utilisateur de la couche et la couche de base (avec la logique d'entreprise, etc.). En général, longue à exécuter les tâches sont exécutées dans le cadre d'un thread (peut-être via AsyncTask ou HandlerThread si l'aide d' MessageQueues) à l'intérieur de la couche de base et l'INTERFACE utilisateur doit être mis à jour une fois cette tâche terminée. En général, avec des rappels de vous réaliser un couplage étroit entre vos composants, donc je préfère l'utilisation de cette approche uniquement à l'intérieur de la couche et pas de communication au travers de la couche de limites. Pour la diffusion de messages entre l'INTERFACE utilisateur et la base de la couche, j'utilisais l' BroadcastReceiver-approche qui vous permet de découpler l'INTERFACE de la couche de la couche logique.

6voto

Alex Points 15303

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

3voto

objbuilder Points 200

Je vais juste ajouter une autre option pour les autres réponses que vous avez déjà reçus...

Vous n'avez pas à créer un récepteur de radiodiffusion de recevoir des Intentions. Dans votre fichier manifeste android vous pouvez enregistrer toute l'activité de 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 remplacer l' onNewIntent(Intent) méthode de votre activité à le recevoir.

Pour envoyer l'Intention, l'utilisation de l' Context.startActivity(Intent) méthode. Plus probable que vous aurez envie d'ajouter l' FLAG_ACTIVITY_SINGLE_TOP drapeau à votre Intention afin de ne pas créer une nouvelle instance de votre activité si l'on est déjà en cours d'exécution.

EDIT: je viens de remarqué que vous êtes en cours d'exécution au sein d'une seule application. Par conséquent, un simple rappel est probablement le meilleur. La solution ci-dessus ne fonctionne dans une seule application, mais il est plus approprié pour différentes applications. Je vais le laisser ici juste au cas où il aide quelqu'un. Bonne chance!

2voto

silwar Points 1634

Broadcastreceivers doit être utilisé Si vous avez besoin d'envoyer des diffusions à travers les applications, tandis que les Rappels (ou les Gestionnaires comme suggéré par Alex) sont mieux à utiliser dans votre situation.

Si vous souhaitez utiliser d'autres que ces deux-là, pensez à utiliser Observateur (Interface inclus dans android) et de les déléguer.

Pour le délégué, veuillez considérer cette SORTE de post.

Espérons que cela permettra de résoudre votre problème

1voto

android developer Points 20939

pas sûr de ce que l'objectif est bien , mais si vous souhaitez garder la même idée de l'utilisation de l'intention et de broadcastReceiver , et que vous voulez une meilleure performance et de sécurité que la normale broadcastReceivers , vous pouvez essayer cette démo , disponible dans l'android support library :

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

si pas , vous pouvez toujours utiliser asyncTask , de services , gestionnaires , etc...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X