Jak korzystać z LocalBroadcastManager?


452

Jak korzystać / lokalizować LocalBroadcastManagerzgodnie z opisem w Dokumentach Google i dokumencie transmisji usług ?

Próbowałem google go, ale nie ma kodu na początek?

Dokumenty mówią, że powinienem go użyć, jeśli chcę nadawać wewnętrznie w procesie mojej aplikacji, ale nie wiem, gdzie go szukać.

Jakaś pomoc / komentarz?

Aktualizacja : Wiem, jak korzystać z emisji, ale nie wiem, jak uzyskać LocalBroadcastManagerdostęp do mojego projektu.


Waqas, czy zarejestrowałeś odbiorcę w manifeście? Jeśli tak, proszę dać mi znać jak?
Mudassir,

2
Nie sądzę, żebyś musiał ewidencjonować odbiornik dla takich transmisji w sposób oczywisty, ponieważ jeśli tak, to ten odbiornik będzie także nasłuchiwał globalnych transmisji.
waqaslam

2
Prawdziwe. Oznacza to, że muszę to zrobić w kodzie, jak podano w odpowiedzi poniżej; LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("custom-event-name"));
Mudassir,

2
LocalBroadcastManagerzostał wycofany. Mój zastąpiłem biblioteką EventBus, która jest o wiele ładniejsza, imo.
Kris B

Odpowiedzi:


861

I tak odpowiem. Na wypadek, gdyby ktoś tego potrzebował.

ReceiverActivity.java

Aktywność, która obserwuje powiadomienia o zdarzeniu o nazwie "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

Drugie działanie, które wysyła / nadaje powiadomienia.

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

Z powyższego kodu, za każdym razem przycisk R.id.button_sendzostanie kliknięty, zamiarem jest nadawany i odbierany jest przez mMessageReceiverw ReceiverActivity.

Dane wyjściowe debugowania powinny wyglądać następująco:

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! 

7
dzięki. już działa. ale problemem, z którym się spotkałem, było opanowanie klasy LocalBroadcastManager. Ponieważ jest to klasa pakietu wsparcia, więc nie byłem w stanie używać go w moim zwykłym pakiecie, dopóki nie dodałem Biblioteki kompatybilności z Android Tools. Po dodaniu wszystko poszło dobrze. w każdym razie dzięki za odpowiedź
waqaslam

195
pamiętaj, że onDestroy()nie ma gwarancji, że zadzwonisz !!! Musisz użyć onPause()(ponieważ tylko onPause()jest to gwarantowane) i onResume()(ponieważ to pasuje do onPause())
18446744073709551615

5
Ludzie, zwróćcie uwagę na to, co teraz mówią dokumenty Google na temat działania po onPause (): Killable = Pre-HONEYCOMB Począwszy od Honeycomb, aplikacja nie jest w stanie możliwym do odtworzenia, dopóki nie powróci jej funkcja onStop ().
18446744073709551615

59
onDestroy()nie jest problemem. Przypadek, w którym nie jest wywoływany, to moment, w którym aplikacja została zabita, i nie ma znaczenia, że ​​nie wyrejestrujesz się w tym przypadku, ponieważ nawet lista zarejestrowanych odbiorców nie przeżyje.
zapl

4
@Selvin Mam nadzieję, że zdajesz sobie sprawę, że możesz sprawić, że BroadcastReciever będzie słabo powiązany z działaniem odbierającym i sprawi, że sam się wyrejestruje, jeśli zostanie osierocony. Nie musisz go wyrejestrowywać w onPause, onDestroy jest w porządku, o ile nie używasz BroadcastReceiver do utrzymywania aktywności w pamięci RAM. Twój przykład pokazuje złą praktykę, w której klasa wewnętrzna przecieka z klasy zewnętrznej, nie jest ona unikalna dla BroadcastReceiver i jest czymś, przed czym programiści zawsze muszą się wystrzegać. Jeśli chodzi o modyfikowanie interfejsu GUI, możesz zapisać stan, w którym po wznowieniu działania nie musisz modyfikować interfejsu GUI.
JohanShogun

132

Wolę odpowiedzieć kompleksowo.

  1. LocalbroadcastManager zawarty w Androidzie 3.0 i nowszych wersjach, więc musisz używać biblioteki wsparcia v4 dla wczesnych wersji. zobacz instrukcje tutaj

  2. Utwórz odbiornik radiowy:

    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. Zarejestruj swój odbiornik w OnResume działalności, takiej jak:

    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. wyrejestruj odbiornik włączony onPause:

    protected void onPause() {
      super.onPause();
      LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
    }
  5. Teraz za każdym razem, gdy nadawany jest program lokalny z aktywności lub usługi aplikacji, onReceive onNotice będzie wywoływany :).

Edycja: Możesz przeczytać cały samouczek tutaj LocalBroadcastManager: Przekazywanie komunikatów wewnątrz aplikacji


15
+1. jeśli twój odbiornik rozgłoszeniowy znajduje się we fragmencie, zarejestruj go za pomocą LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onNotice);i wyrejestruj za pomocąLocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onNotice);
PeteH

3
Czy jesteś pewien, że LocalBroadcastManager jest dołączony do Androida 3.0 i nowszych? Nie można go nigdzie znaleźć oprócz wsparcia lib
Mente

5
o dziwo, LBM jest zawarty tylko w bibliotece wsparcia.
Jeffrey Blattman,

1
super.onPause () powinna być ostatnią instrukcją podczas nadpisywania metody onPause. Wyrejestruj się przed super.onPauzą, aby uniknąć nieprzewidzianego błędu
Thupten,

2
Wydaje mi się, że możesz chcieć przenieść swój cykl życia, onStopponieważ w Android API 24+ z „Multi-Window / Split-View” (domyślnie włączony w aaicr API 26+) aktywność, z którą nie wchodzi się w interakcję, jest wstrzymana. Źródło: developer.android.com/guide/topics/ui/…
Martin Marconcini,

45

Po zakończeniu odbioru:

  • Najpierw zarejestruj odbiornik LocalBroadcast
  • Następnie obsługuj przychodzące dane zamiaru w 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 
              }
          }
      };

Po zakończeniu wysyłania:

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

   LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

W moim przypadku tylko wtedy, gdy ustawiam działanie w sposób zamierzony, gdy wysyłanie transmisji działa inaczej metoda onReceive () nigdy nie
wywołała

27

W Eclipse ostatecznie musiałem dodać bibliotekę kompatybilności / obsługi technicznej, klikając prawym przyciskiem myszy mój projekt i wybierając:

Android Tools -> Add Support Library

Po dodaniu mogłem użyć LocalBroadcastManagerklasy w moim kodzie.


Biblioteka kompatybilności z Androidem


12

Jak zmienić globalną transmisję na LocalBroadcast

1) Utwórz instancję

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);

2) Do rejestracji BroadcastReceiver

Zastąpić

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

Z

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

3) Do wysyłania wiadomości rozgłoszeniowej

Zastąpić

sendBroadcast(intent);

Z

localBroadcastManager.sendBroadcast(intent);

4) Za wyrejestrowanie wiadomości rozgłoszeniowej

Zastąpić

unregisterReceiver(mybroadcast);

Z

localBroadcastManager.unregisterReceiver(mybroadcast);

Jak mogę zarejestrować wiele filtrów IntentFilter?
Parikshit Chalke

@ParikshitChalke: link
XMAN,

12

localbroadcastmanager jest przestarzały, zamiast tego użyj implementacji obserwowalnego wzorca.

androidx.localbroadcastmanager jest przestarzałe w wersji 1.1.0

Powód

LocalBroadcastManagerjest aplikacyjną szyną zdarzeń i obejmuje naruszenia aplikacji w Twojej aplikacji; dowolny komponent może nasłuchiwać zdarzeń z dowolnego innego komponentu. Dziedziczy niepotrzebne ograniczenia przypadków użycia systemu BroadcastManager; programiści muszą korzystać z Intent, nawet jeśli obiekty działają tylko w jednym procesie i nigdy go nie opuszczają. Z tego samego powodu nie jest zgodny z funkcją BroadcastManager pod względem funkcji.

To wszystko powoduje zamieszanie programistów.

Zastąpienie

Możesz zastąpić użycie LocalBroadcastManagerinnymi implementacjami obserwowalnego wzorca. W zależności od przypadku zastosowania odpowiednimi opcjami mogą być LiveDatalub strumienie reaktywne.

Zaleta LiveData

Możesz rozszerzyć LiveDataobiekt za pomocą wzorca singleton, aby zawinąć usługi systemowe, aby można je było udostępnić w aplikacji. Na LiveDatałączy sprzeciw wobec usługi systemowej jednokrotnie, a następnie każdego obserwatora, który potrzebuje zasobu może tylko obserwować LiveDataobiekt.

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

observe()Sposób przechodzi do fragmentu, który jest przykładem LifecycleOwner, jak pierwszy argument. Oznacza to, że ten obserwator jest powiązany z Lifecycleobiektem powiązanym z właścicielem, co oznacza:

  • Jeśli obiekt Lifecycle nie jest w stanie aktywnym, obserwator nie jest wywoływany, nawet jeśli wartość się zmienia.

  • Po zniszczeniu obiektu Lifecycle obserwator jest automatycznie usuwany

Fakt, że LiveDataobiekty uwzględniają cykl życia, oznacza, że ​​można je udostępniać między wieloma działaniami, fragmentami i usługami.


1
masz rację, jeśli chodzi o wyciekanie kontekstów do całego świata, ale chciałbym wiedzieć, co byłoby odpowiednim zamiennikiem, gdy chcę komunikować się z usługą pierwszego planu, która działa nawet bez aktywności, ale kiedy przychodzi aktywność, muszą się komunikować?
ateebahmed

1
Utwórz klasę singleton z obiektem LiveData i opublikuj swoje dane z usługi. Po uruchomieniu działania aktywność może łatwo obserwować LiveData bez szkody. np .: MyServiceData.getInstance (). getMyData (). zaobserwuj ...
Darish

3
Będę tęsknić za LocalBroadcastManager. Jeśli było to mylące dla programistów w Google, być może muszą oni przestać nad-inżynierować?
AFD

@Darish Czy ta klasa singletonów byłaby równoważna przechowywaniu jej w obiekcie aplikacji? Dlaczego tego rodzaju stan globalny w tych przypadkach nie jest uważany za złą praktykę?
xuiqzy

6

Kiedy będziesz grać wystarczająco dużo z LocalBroadcastReceiver, zasugeruję Ci wypróbowanie EventBus Green Robot - na pewno zauważysz różnicę i użyteczność tego w porównaniu z LBR. Mniej kodu, możliwość dostosowania do wątku odbiorcy (UI / Bg), sprawdzania dostępności odbiorników, zdarzeń trwałych, zdarzeń może służyć jako dostawa danych itp.



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

0

Deklarując jeden w pliku AndroidManifest.xml za pomocą znacznika (zwanego także statycznym)

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

Zauważysz, że zadeklarowany powyżej odbiornik radiowy ma właściwość exported = „true”. Ten atrybut informuje odbiorcę, że może odbierać transmisje spoza zakresu aplikacji.
2. Lub dynamicznie, rejestrując instancję w registerReceiver (tak zwany kontekst zarejestrowany)

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

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

Istnieją trzy sposoby wysyłania transmisji:
Metoda sendOrdersBroadcast zapewnia wysyłanie transmisji tylko do jednego odbiornika na raz. Każda transmisja może z kolei przekazywać dane do kolejnej po niej lub zatrzymać propagację transmisji do następnych odbiorników.
SendBroadcast jest podobny do metody wspomnianej powyżej, z jedną różnicą. Wszystkie odbiorniki radiowe odbierają wiadomość i nie są od siebie zależne.
Metoda LocalBroadcastManager.sendBroadcast wysyła tylko transmisje do odbiorników zdefiniowanych w aplikacji i nie wykracza poza zakres aplikacji.


-4

możemy również użyć interfejsu dla samego jak broadcastManger. Udostępniam kod testd dla broadcastManager, ale według interfejsu.

najpierw utwórz interfejs taki jak:

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

2 - jest to pierwsza klasa, która wymaga implementacji

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-tutaj jest druga klasa, która implementuje ten sam interfejs, którego metoda wywołuje automatycznie

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

dzięki temu podejściu możemy użyć interfejsu działającego tak samo jak broadcastManager.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.