Comment utiliser LocalBroadcastManager?

452

Comment utiliser / localiser LocalBroadcastManagercomme décrit dans google docs et Service broadcast doc ?

J'ai essayé de le chercher sur Google, mais il n'y a pas de code disponible pour commencer?

Les documents disent que je devrais l'utiliser si je veux faire de la diffusion en interne avec dans le processus de mon application, mais je ne sais pas où chercher.

Une aide / un commentaire?

Mise à jour : je sais comment utiliser les diffusions mais je ne sais pas comment être LocalBroadcastManagerdisponible dans mon projet.

waqaslam
la source
Waqas, avez-vous enregistré le destinataire dans le manifeste. Si oui, faites-le moi savoir comment?
Mudassir
2
Je ne pense pas que vous ayez besoin d'enregistrer le récepteur pour de telles émissions dans le manifeste, car si vous le faites, ce récepteur écoutera également les émissions mondiales.
waqaslam
2
Vrai. Ensuite, cela signifie que je dois le faire en code comme indiqué dans la réponse ci-dessous; LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("custom-event-name"));
Mudassir
2
LocalBroadcastManagerest obsolète. J'ai remplacé la mienne par la bibliothèque EventBus qui est beaucoup plus agréable, imo.
Kris B

Réponses:

862

J'y répondrai quand même. Juste au cas où quelqu'un en aurait besoin.

ReceiverActivity.java

Une activité qui surveille les notifications de l'événement nommé "custom-event-name".

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Register to receive messages.
  // We are registering an observer (mMessageReceiver) to receive Intents
  // with actions named "custom-event-name".
  LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
      new IntentFilter("custom-event-name"));
}

// Our handler for received Intents. This will be called whenever an Intent
// with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Get extra data included in the Intent
    String message = intent.getStringExtra("message");
    Log.d("receiver", "Got message: " + message);
  }
};

@Override
protected void onDestroy() {
  // Unregister since the activity is about to be closed.
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
  super.onDestroy();
}

SenderActivity.java

La deuxième activité qui envoie / diffuse des notifications.

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Every time a button is clicked, we want to broadcast a notification.
  findViewById(R.id.button_send).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      sendMessage();
    }
  });
}

// Send an Intent with an action named "custom-event-name". The Intent sent should 
// be received by the ReceiverActivity.
private void sendMessage() {
  Log.d("sender", "Broadcasting message");
  Intent intent = new Intent("custom-event-name");
  // You can also include some extra data.
  intent.putExtra("message", "This is my message!");
  LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

Avec le code ci-dessus, chaque fois que le bouton R.id.button_sendest cliqué, une intention est diffusée et reçue par mMessageReceiverin ReceiverActivity.

La sortie de débogage devrait ressembler à ceci:

01-16 10:35:42.413: D/sender(356): Broadcasting message
01-16 10:35:42.421: D/receiver(356): Got message: This is my message! 
Shiki
la source
7
Merci. l'a déjà fait fonctionner. mais le problème que j'ai rencontré était de mettre la main sur la classe LocalBroadcastManager. Étant donné que c'est une classe de package de support, je n'ai donc pas pu l'utiliser dans mon package ordinaire jusqu'à ce que j'ajoute la bibliothèque de compatibilité des outils Android. Une fois ajouté, tout s'est très bien passé. de toute façon, merci pour la réponse
waqaslam
195
veuillez noter qu'il onDestroy()n'est pas garanti d'être appelé !!! Vous devez utiliser onPause()(car seul onPause()est garanti) et onResume()(car c'est le match pour onPause())
18446744073709551615
5
Mes amis, notez ce que les documents de Google disent maintenant sur une activité après onPause (): Killable = Pre-HONEYCOMB À partir de Honeycomb, une application n'est pas dans l'état killable tant que son onStop () n'est pas revenu.
18446744073709551615
59
onDestroy()n'est pas un problème. Le cas où elle n'est pas appelée, c'est quand l'application est tuée, et peu importe si vous ne vous désinscrivez pas dans ce cas, car même la liste des récepteurs enregistrés ne survit pas.
zapl
4
@Selvin J'espère que vous savez que vous pouvez rendre le BroadcastReciever faiblement référencé à l'activité de réception et le faire se désinscrire lui-même s'il est orphelin. Vous n'avez pas besoin de le désinscrire dans onPause, onDestroy va bien tant que vous n'utilisez pas votre BroadcastReceiver pour garder votre activité dans la RAM. Votre exemple montre une mauvaise pratique avec une classe interne qui fuit sa classe externe, ce n'est pas unique à BroadcastReceiver et c'est quelque chose que les programmeurs doivent toujours se prémunir. Quant à la modification de l'interface graphique, vous pouvez stocker un état pour quand l'activité est reprise, vous n'avez pas à modifier l'interface graphique.
JohanShogun
133

Je préfère répondre de manière globale.

  1. LocalbroadcastManager inclus dans Android 3.0 et supérieur, vous devez donc utiliser la bibliothèque de support v4 pour les premières versions. voir les instructions ici

  2. Créez un récepteur de diffusion:

    private BroadcastReceiver onNotice= new BroadcastReceiver() {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            // intent can contain anydata
            Log.d("sohail","onReceive called");
            tv.setText("Broadcast received !");
    
        }
    };
  3. Enregistrez votre récepteur sur une reprise d'activité comme:

    protected void onResume() {
            super.onResume();
    
            IntentFilter iff= new IntentFilter(MyIntentService.ACTION);
            LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, iff);
        }
    
    //MyIntentService.ACTION is just a public static string defined in MyIntentService.
  4. désenregistrer le récepteur en onPause:

    protected void onPause() {
      super.onPause();
      LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
    }
  5. Désormais, chaque fois qu'une diffusion locale est envoyée à partir de l'activité ou du service des applications, onReceive de onNotice sera appelé :).

Edit: Vous pouvez lire le tutoriel complet ici LocalBroadcastManager: passage de message intra application

SohailAziz
la source
15
+1. si votre récepteur de diffusion est dans un fragment, enregistrez-le en utilisant LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onNotice);et désenregistrez-le en utilisantLocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onNotice);
PeteH
3
Êtes-vous sûr que LocalBroadcastManager est inclus dans Android 3.0 et versions ultérieures? Je ne le trouve nulle part sauf le support lib
mente
5
étrangement, LBM n'est inclus que dans la bibliothèque de support.
Jeffrey Blattman
1
super.onPause () doit être la dernière instruction lors du remplacement de la méthode onPause. Se désinscrire avant super.onPause pour éviter un bug imprévisible
Thupten
2
Je pense que vous souhaiterez peut-être déplacer votre cycle de vie onStopcar dans Android API 24+ avec «Multi-Window / Split-View» (activé par défaut sur l'API 26+ affaicr), l'activité qui n'est pas interagie est en état de pause. Source: developer.android.com/guide/topics/ui/…
Martin Marconcini
45

À la réception:

  • Enregistrez d'abord LocalBroadcast Receiver
  • Ensuite, gérez les données d'intention entrantes dans onReceive.

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
    
          LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
          lbm.registerReceiver(receiver, new IntentFilter("filter_string"));
      }
    
      public BroadcastReceiver receiver = new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
              if (intent != null) {
                  String str = intent.getStringExtra("key");
                  // get all your data from intent and do what you want 
              }
          }
      };

À la fin de l'envoi:

   Intent intent = new Intent("filter_string");
   intent.putExtra("key", "My Data");
   // put your all data using put extra 

   LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
waqas ali
la source
Dans mon cas, uniquement lorsque j'ai défini une action intentionnelle lors de l'envoi de travaux de diffusion, sinon la méthode onReceive () n'a jamais été appelée ...
Akash Bisariya
27

Dans Eclipse, j'ai finalement dû ajouter la bibliothèque de compatibilité / support en cliquant avec le bouton droit sur mon projet et en sélectionnant:

Android Tools -> Add Support Library

Une fois qu'il a été ajouté, j'ai pu utiliser la LocalBroadcastManagerclasse dans mon code.


Bibliothèque de compatibilité Android

waqaslam
la source
13

localbroadcastmanager est obsolète, utilisez plutôt des implémentations du modèle observable.

androidx.localbroadcastmanager est déconseillé dans la version 1.1.0

Raison

LocalBroadcastManagerest un bus d'événements à l'échelle de l'application et intègre les violations de couche dans votre application; tout composant peut écouter les événements de tout autre composant. Il hérite des limitations inutiles de cas d'utilisation du système BroadcastManager; les développeurs doivent utiliser Intent même si les objets vivent dans un seul processus et ne le quittent jamais. Pour cette même raison, il ne suit pas BroadcastManager en termes de fonctionnalités.

Ceux-ci s'ajoutent à une expérience de développeur déroutante.

Remplacement

Vous pouvez remplacer l'utilisation de LocalBroadcastManagerpar d'autres implémentations du modèle observable. Selon votre cas d'utilisation, des options appropriées peuvent être LiveDatades flux réactifs.

Avantage de LiveData

Vous pouvez étendre un LiveDataobjet à l'aide du modèle singleton pour envelopper les services système afin qu'ils puissent être partagés dans votre application. L' LiveDataobjet se connecte au service système une fois, puis tout observateur qui a besoin de la ressource peut simplement regarder l' LiveDataobjet.

 public class MyFragment extends Fragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        LiveData<BigDecimal> myPriceListener = ...;
        myPriceListener.observe(this, price -> {
            // Update the UI.
        });
    }
}

La observe()méthode passe le fragment, qui est une instance de LifecycleOwner, comme premier argument. Cela signifie que cet observateur est lié à l' Lifecycleobjet associé au propriétaire, ce qui signifie:

  • Si l'objet Cycle de vie n'est pas dans un état actif, l'observateur n'est pas appelé même si la valeur change.

  • Une fois l'objet Cycle de vie détruit, l'observateur est automatiquement supprimé

Le fait que les LiveDataobjets soient sensibles au cycle de vie signifie que vous pouvez les partager entre plusieurs activités, fragments et services.

Darish
la source
1
vous avez raison de divulguer des contextes au monde entier, mais j'aimerais savoir quel serait un remplacement approprié lorsque je veux communiquer à partir d'un service de premier plan qui s'exécute même sans activité, mais quand une activité entre, ils doivent communiquer?
ateebahmed
2
Créez une classe singleton avec un objet LiveData et publiez vos données à partir du service. Une fois l'activité lancée, l'activité peut facilement observer les LiveData sans aucun dommage. par exemple: MyServiceData.getInstance (). getMyData (). observez ...
Darish
3
LocalBroadcastManager me manquera. Si c'était déroutant pour les développeurs de Google, peut-être qu'ils doivent arrêter les choses de suringénierie?
AFD
@Darish Cette classe singleton équivaudrait-elle à la stocker dans l'objet Application? Pourquoi ce type d'État mondial dans ces cas n'est pas considéré comme une mauvaise pratique?
xuiqzy
12

Comment changer votre diffusion mondiale en LocalBroadcast

1) Créer une instance

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);

2) Pour enregistrer BroadcastReceiver

Remplacer

registerReceiver(new YourReceiver(),new IntentFilter("YourAction"));

Avec

localBroadcastManager.registerReceiver(new YourReceiver(),new IntentFilter("YourAction"));

3) Pour l'envoi d'un message diffusé

Remplacer

sendBroadcast(intent);

Avec

localBroadcastManager.sendBroadcast(intent);

4) Pour désenregistrer un message diffusé

Remplacer

unregisterReceiver(mybroadcast);

Avec

localBroadcastManager.unregisterReceiver(mybroadcast);
Rohit Singh
la source
Comment puis-je enregistrer plusieurs IntentFilter ??
Parikshit Chalke
@ParikshitChalke: lien
XMAN
6

Lorsque vous jouerez suffisamment avec LocalBroadcastReceiver, je vous suggérerai d' essayer l'EventBus de Green Robot - vous en comprendrez certainement la différence et l'utilité par rapport à LBR. Moins de code, personnalisable sur le thread du récepteur (UI / Bg), vérifiant la disponibilité des récepteurs, les événements collants, les événements peuvent être utilisés comme livraison de données, etc.

Stan
la source
2

Un exemple d'activité et de service implémentant un LocalBroadcastManager peut être trouvé dans les documents du développeur . Je l'ai personnellement trouvé très utile.

EDIT: Le lien a depuis été supprimé du site, mais les données sont les suivantes: https://github.com/carrot-garden/android_maven-android-plugin-samples/blob/master/support4demos/src/com/ exemple / android / supportv4 / content / LocalServiceBroadcaster.java

nindalf
la source
0
enter code here if (createSuccses){
                        val userDataChange=Intent(BRODCAST_USER_DATA_CHANGE)
                        LocalBroadcastManager.getInstance(this).sendBroadcast(
                            userDataChange
                        )
                        enableSpinner(false)
                        finish()
Seroj Grigoryan
la source
0

En en déclarant un dans votre fichier AndroidManifest.xml avec la balise (également appelée statique)

<receiver android:name=".YourBrodcastReceiverClass"  android:exported="true">
<intent-filter>
    <!-- The actions you wish to listen to, below is an example -->
    <action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>

Vous remarquerez que le récepteur de diffusion déclaré ci-dessus a une propriété de exports = "true". Cet attribut indique au récepteur qu'il peut recevoir des émissions de l'extérieur de la portée de l'application.
2. Ou dynamiquement en enregistrant une instance avec registerReceiver (ce que l'on appelle le contexte enregistré)

public abstract Intent registerReceiver (BroadcastReceiver receiver, 
            IntentFilter filter);

public void onReceive(Context context, Intent intent) {
//Implement your logic here
}

Il existe trois façons d'envoyer des diffusions:
La méthode sendOrderedBroadcast garantit l'envoi des diffusions à un seul récepteur à la fois. Chaque diffusion peut à son tour, transmettre des données à celle qui la suit, ou arrêter la propagation de la diffusion aux récepteurs qui suivent.
Le sendBroadcast est similaire à la méthode mentionnée ci-dessus, avec une différence. Tous les récepteurs de diffusion reçoivent le message et ne dépendent pas les uns des autres.
La méthode LocalBroadcastManager.sendBroadcast envoie uniquement des diffusions aux récepteurs définis dans votre application et ne dépasse pas la portée de votre application.

Seroj Grigoryan
la source
-4

nous pouvons également utiliser l'interface pour le même que broadcastManger ici, je partage le code testd pour broadcastManager mais par interface.

faire d'abord une interface comme:

public interface MyInterface {
     void GetName(String name);
}

2-c'est la première classe à implémenter

public class First implements MyInterface{

    MyInterface interfc;    
    public static void main(String[] args) {
      First f=new First();      
      Second s=new Second();
      f.initIterface(s);
      f.GetName("Paddy");
  }
  private void initIterface(MyInterface interfc){
    this.interfc=interfc;
  }
  public void GetName(String name) {
    System.out.println("first "+name);
    interfc.GetName(name);  
  }
}

3-voici la deuxième classe qui implémente la même interface dont la méthode appelle automatiquement

public class Second implements MyInterface{
   public void GetName(String name) {
     System.out.println("Second"+name);
   }
}

donc par cette approche, nous pouvons utiliser l'interface fonctionnant de la même manière que broadcastManager.

padmender singh
la source