Wie verwende ich LocalBroadcastManager?

452

Wie verwende / finde ichLocalBroadcastManager wie in Google Docs und Service Broadcast Doc beschrieben ?

Ich habe versucht, es zu googeln, aber es ist zunächst kein Code verfügbar?

Die Dokumente besagen, dass ich es verwenden sollte, wenn ich im Prozess meiner App intern senden möchte, aber ich weiß nicht, wo ich danach suchen soll.

Hilfe / Kommentar?

Update : Ich weiß, wie man Broadcasts verwendet, weiß aber nicht, wie ich LocalBroadcastManagerin meinem Projekt verfügbar werde.

Waqaslam
quelle
Waqas, haben Sie den Empfänger im Manifest registriert? Wenn ja, lassen Sie mich bitte wissen, wie?
Mudassir
2
Ich glaube nicht, dass Sie den Empfänger für solche Sendungen im Manifest registrieren müssen, denn wenn Sie dies tun, wird dieser Empfänger auch auf globale Sendungen warten.
Waqaslam
2
Wahr. Dann bedeutet dies, dass ich es im Code tun muss, wie in der Antwort unten angegeben; LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("custom-event-name"));
Mudassir
2
LocalBroadcastManagerwurde veraltet. Ich habe meine durch die EventBus-Bibliothek ersetzt, die viel schöner ist, imo.
Kris B

Antworten:

861

Ich werde das trotzdem beantworten. Nur für den Fall, dass jemand es braucht.

ReceiverActivity.java

Eine Aktivität, die nach Benachrichtigungen für das genannte Ereignis sucht "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

Die zweite Aktivität, die Benachrichtigungen sendet / sendet.

@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);
}

Mit dem obigen Code wird jedes Mal, wenn auf die Schaltfläche R.id.button_sendgeklickt wird, eine Absicht gesendet und von mMessageReceiverin empfangen ReceiverActivity.

Die Debug-Ausgabe sollte folgendermaßen aussehen:

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
quelle
7
Vielen Dank. habe es schon zum Laufen gebracht. Aber das Problem, mit dem ich konfrontiert war, war, die LocalBroadcastManager-Klasse zu erreichen. Da es sich um eine Support Package-Klasse handelt, konnte ich sie in meinem normalen Paket erst verwenden, als ich die Kompatibilitätsbibliothek von Android Tools hinzugefügt habe. Sobald es hinzugefügt wurde, ging alles gut.
Trotzdem
195
Bitte beachten Sie, dass der onDestroy()Anruf nicht garantiert ist !!! Sie müssen verwenden onPause()(weil nur onPause()garantiert ist) und onResume()(weil es das Match für ist onPause())
18446744073709551615
5
Leute, beachten Sie, was die Google-Dokumente jetzt über eine Aktivität nach onPause () sagen: Killable = Pre-HONEYCOMB Ab Honeycomb befindet sich eine Anwendung erst im Status killable, wenn onStop () zurückgegeben wurde.
18446744073709551615
59
onDestroy()es ist kein Problem. Der Fall, in dem es nicht aufgerufen wird, ist, wenn die App beendet wird, und es spielt keine Rolle, ob Sie die Registrierung in diesem Fall nicht aufheben, da nicht einmal die Liste der registrierten Empfänger dies überlebt.
Zapl
4
@ Selvin Ich hoffe, Sie wissen, dass Sie den BroadcastReciever schwach auf die empfangende Aktivität verweisen und die Registrierung selbst aufheben können, wenn er verwaist ist. Sie müssen die Registrierung in onPause nicht aufheben. OnDestroy ist in Ordnung, solange Sie Ihren BroadcastReceiver nicht verwenden, um Ihre Aktivitäten im RAM zu halten. Ihr Beispiel zeigt eine schlechte Praxis, bei der eine innere Klasse ihre äußere Klasse verliert. Dies gilt nicht nur für BroadcastReceiver und ist etwas, vor dem sich Programmierer immer schützen müssen. Zum Ändern der GUI können Sie einen Status speichern, wenn die Aktivität wieder aufgenommen wird und Sie die GUI nicht ändern müssen.
JohanShogun
133

Ich möchte lieber umfassend antworten.

  1. LocalbroadcastManager ist in Android 3.0 und höher enthalten, daher müssen Sie die Support-Bibliothek v4 für frühere Versionen verwenden. Anweisungen hier

  2. Erstellen Sie einen Rundfunkempfänger:

    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. Registrieren Sie Ihren Empfänger in onResume of activity wie:

    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. Empfänger in onPause abmelden:

    protected void onPause() {
      super.onPause();
      LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
    }
    
  5. Immer wenn ein lokaler Broadcast von der Aktivität oder dem Dienst der Anwendung gesendet wird, wird onReceive of onNotice aufgerufen :).

Bearbeiten: Sie können das vollständige Tutorial hier lesen. LocalBroadcastManager: Intra Application Message Passing

SohailAziz
quelle
15
+1. Wenn sich Ihr Rundfunkempfänger in einem Fragment befindet, registrieren Sie ihn mit LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onNotice);und LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onNotice);
entfernen
3
Sind Sie sicher, dass LocalBroadcastManager in Android 3.0 und höher enthalten ist? Kann es nirgendwo finden, außer Support lib
mente
5
Seltsamerweise ist LBM nur in der Support-Bibliothek enthalten.
Jeffrey Blattman
1
super.onPause () sollte die letzte Anweisung sein, wenn die onPause-Methode überschrieben wird. Vor super.on abmelden, um unvorhersehbare Fehler zu vermeiden
Thupten
2
Ich glaube, Sie möchten möglicherweise Ihren Lebenszyklus verschieben, onStopda in Android API 24+ mit "Multi-Window / Split-View" (standardmäßig aktiviert auf API 26+ affaicr) die Aktivität, mit der nicht interagiert wird, angehalten ist. Quelle: developer.android.com/guide/topics/ui/…
Martin Marconcini
45

Am Empfangsende:

  • Registrieren Sie zuerst den LocalBroadcast-Empfänger
  • Behandeln Sie dann eingehende Absichtsdaten in 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 
              }
          }
      };
    

Am Sendeende:

   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
quelle
In meinem Fall nur, wenn ich beim Senden von Broadcast-Arbeiten absichtlich eine Aktion festgelegt habe, wird die onReceive () -Methode ansonsten nie aufgerufen ...
Akash Bisariya
27

In Eclipse musste ich schließlich die Kompatibilitäts- / Supportbibliothek hinzufügen, indem ich mit der rechten Maustaste auf mein Projekt klickte und Folgendes auswählte:

Android Tools -> Add Support Library

Sobald es hinzugefügt wurde, konnte ich LocalBroadcastManagerKlasse in meinem Code verwenden.


Android-Kompatibilitätsbibliothek

Waqaslam
quelle
12

So ändern Sie Ihre globale Sendung in LocalBroadcast

1) Instanz erstellen

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);

2) Zur Registrierung von BroadcastReceiver

Ersetzen

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

Mit

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

3) Zum Senden einer Broadcast-Nachricht

Ersetzen

sendBroadcast(intent);

Mit

localBroadcastManager.sendBroadcast(intent);

4) Zum Aufheben der Registrierung der Broadcast-Nachricht

Ersetzen

unregisterReceiver(mybroadcast);

Mit

localBroadcastManager.unregisterReceiver(mybroadcast);
Rohit Singh
quelle
Wie kann ich mehrere IntentFilter registrieren?
Parikshit Chalke
@ParikshitChalke: Link
XMAN
12

localbroadcastmanager ist veraltet. Verwenden Sie stattdessen Implementierungen des beobachtbaren Musters.

androidx.localbroadcastmanager wird in Version 1.1.0 nicht mehr unterstützt

Grund

LocalBroadcastManagerist ein anwendungsweiter Ereignisbus und berücksichtigt Ebenenverletzungen in Ihrer App. Jede Komponente kann Ereignisse von jeder anderen Komponente abhören. Es erbt unnötige Anwendungsfallbeschränkungen des Systems BroadcastManager. Entwickler müssen Intent verwenden, obwohl Objekte nur in einem Prozess leben und ihn niemals verlassen. Aus dem gleichen Grund folgt es nicht dem funktionsweisen BroadcastManager.

Dies führt zu einer verwirrenden Entwicklererfahrung.

Ersatz

Sie können die Verwendung von LocalBroadcastManagerdurch andere Implementierungen des beobachtbaren Musters ersetzen. Abhängig von Ihrem Anwendungsfall können geeignete Optionen LiveDataoder reaktive Streams sein.

Vorteil von LiveData

Sie können ein LiveDataObjekt mithilfe des Singleton-Musters erweitern, um Systemdienste so zu verpacken, dass sie in Ihrer App freigegeben werden können. Das LiveDataObjekt stellt einmal eine Verbindung zum Systemdienst her, und dann kann jeder Beobachter, der die Ressource benötigt, das LiveDataObjekt einfach beobachten .

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

Die observe()Methode übergibt das Fragment, bei dem es sich um eine Instanz handelt LifecycleOwner, als erstes Argument. Dies bedeutet, dass dieser Beobachter an das Lifecycledem Eigentümer zugeordnete Objekt gebunden ist , was bedeutet:

  • Wenn sich das Lifecycle-Objekt nicht in einem aktiven Zustand befindet, wird der Beobachter auch dann nicht aufgerufen, wenn sich der Wert ändert.

  • Nachdem das Lifecycle-Objekt zerstört wurde, wird der Beobachter automatisch entfernt

Die Tatsache, dass LiveDataObjekte lebenszyklusabhängig sind, bedeutet, dass Sie sie für mehrere Aktivitäten, Fragmente und Dienste freigeben können.

Darish
quelle
1
Sie haben Recht damit, Kontexte in die ganze Welt zu übertragen, aber ich möchte wissen, was ein geeigneter Ersatz wäre, wenn ich von einem Vordergrunddienst aus kommunizieren möchte, der auch ohne Aktivität ausgeführt wird. Wenn jedoch eine Aktivität eingeht, müssen sie kommunizieren?
Ateebahmed
1
Erstellen Sie eine Singleton-Klasse mit einem LiveData-Objekt und veröffentlichen Sie Ihre Daten aus dem Dienst. Sobald die Aktivität gestartet ist, kann die Aktivität die LiveData problemlos ohne Schaden beobachten. Beispiel: MyServiceData.getInstance (). getMyData (). Beobachten ...
Darish
3
Ich werde LocalBroadcastManager vermissen. Wenn es für Entwickler bei Google verwirrend war, müssen sie vielleicht aufhören, Dinge zu überarbeiten?
AFD
@Darish Wäre diese Singleton-Klasse gleichbedeutend mit dem Speichern im Application-Objekt? Warum wird diese Art von globalem Staat in diesen Fällen nicht als schlechte Praxis angesehen?
xuiqzy
6

Wenn Sie genug mit LocalBroadcastReceiver spielen, empfehle ich Ihnen, den EventBus von Green Robot auszuprobieren - Sie werden den Unterschied und die Nützlichkeit von EventBus im Vergleich zu LBR auf jeden Fall erkennen. Weniger Code, anpassbar an den Thread des Empfängers (UI / Bg), Überprüfung der Verfügbarkeit des Empfängers, Sticky-Ereignisse, Ereignisse können als Datenübermittlung usw. verwendet werden.

Stan
quelle
2

Ein Beispiel für eine Aktivität und ein Dienst eine LocalBroadcastManager Implementierung in den Entwickler finden docs . Ich persönlich fand es sehr nützlich.

BEARBEITEN: Der Link wurde seitdem von der Website entfernt, aber die Daten lauten wie folgt: https://github.com/carrot-garden/android_maven-android-plugin-samples/blob/master/support4demos/src/com/ Beispiel / android / supportv4 / content / LocalServiceBroadcaster.java

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

Indem Sie eine in Ihrer AndroidManifest.xml-Datei mit dem Tag deklarieren (auch als statisch bezeichnet)

<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>

Sie werden feststellen, dass der oben deklarierte Rundfunkempfänger die Eigenschaft exported = "true" hat. Dieses Attribut teilt dem Empfänger mit, dass er Broadcasts von außerhalb des Anwendungsbereichs empfangen kann.
2. Oder dynamisch durch Registrieren einer Instanz bei registerReceiver (sogenannter Kontext registriert)

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

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

Es gibt drei Möglichkeiten, Broadcasts zu senden:
Die sendOrderedBroadcast-Methode stellt sicher, dass Broadcasts jeweils nur an einen Empfänger gesendet werden. Jede Sendung kann wiederum Daten an die folgende Sendung weiterleiten oder die Weitergabe der Sendung an die folgenden Empfänger stoppen.
Der sendBroadcast ähnelt der oben genannten Methode, mit einem Unterschied. Alle Rundfunkempfänger empfangen die Nachricht und sind nicht voneinander abhängig.
Die LocalBroadcastManager.sendBroadcast-Methode sendet nur Broadcasts an Empfänger, die in Ihrer Anwendung definiert sind, und überschreitet nicht den Umfang Ihrer Anwendung.

Seroj Grigoryan
quelle
-4

Wir können hier auch die Schnittstelle für BroadcastManger verwenden. Ich teile den Testcode für BroadcastManager, aber nach Schnittstelle.

Machen Sie zuerst eine Schnittstelle wie:

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

2-Dies ist die erste Klasse, die implementiert werden muss

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-hier ist die zweite Klasse, die dieselbe Schnittstelle implementiert, deren Methode automatisch aufgerufen wird

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

Durch diesen Ansatz können wir die Schnittstelle verwenden, die genauso funktioniert wie BroadcastManager.

Padmender singh
quelle