Як користуватися LocalBroadcastManager?


452

Як використовувати / знайти, LocalBroadcastManagerяк описано в документах google та документі службового мовлення ?

Я спробував google це, але немає коду для початку?

У документах сказано, що я повинен використовувати його, якщо хочу робити внутрішню трансляцію в процесі свого додатка, але я не знаю, де це шукати.

Будь-яка допомога / коментар?

Оновлення : я знаю, як користуватися трансляціями, але не знаю, як отримати LocalBroadcastManagerдоступ до мого проекту.


Waqas, чи зареєстрували ви приймач у маніфесті. Якщо так, будь ласка, дайте мені знати, як?
Мудассір

2
Я не думаю, що вам потрібно зареєструвати приймач для таких передач у маніфесті, тому що якщо ви це зробите, то цей приймач також буде слухати глобальні трансляції.
waqaslam

2
Правда. Тоді це означає, що я повинен це робити за кодом, як зазначено у відповіді нижче; LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("custom-event-name"));
Мудассір

2
LocalBroadcastManagerзастаріло. Я замінив свою бібліотеку на EventBus, що набагато приємніше, іме.
Кріс Б

Відповіді:


862

Я все одно відповім на це. Про всяк випадок, коли комусь це потрібно.

ReceiverActivity.java

Дія, яка спостерігає за сповіщеннями про подію з назвою "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

Другий вид діяльності, який надсилає / транслює сповіщення.

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

З урахуванням зазначених вище, кожен раз , коли кнопка коду R.id.button_sendклацнули, умисел транслюється і приймається mMessageReceiverв ReceiverActivity.

Вихід з налагодження повинен виглядати приблизно так:

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
Дякую. це вже працює. але проблема, з якою я стикався, полягала в тому, щоб влаштуватись на клас LocalBroadcastManager. Оскільки його клас підтримки, я не зміг його використовувати у своєму звичайному пакеті, поки я не додав Бібліотеку сумісності з Android Tools. Як тільки його додали, все пішло нормально. все одно, дякую за відповідь
waqaslam

195
зверніть увагу, що onDestroy()дзвонити не гарантовано !!! Ви повинні використовувати onPause()(тому що лише onPause()гарантовано) та onResume()(тому що це збіг onPause())
18446744073709551615

5
Люди, зауважте, що документи Google зараз говорять про активність після onPause (): Killable = Pre-HONEYCOMB Починаючи з Honeycomb, додаток не знаходиться в стані, що підлягає вбиттю, доки його повернення onStop () не повернеться.
18446744073709551615

59
onDestroy()не проблема. Випадок, коли він не викликається, - це коли програма вбита, і не має значення, якщо ви не скасуєте реєстрацію в цьому випадку, оскільки навіть перелік зареєстрованих приймачів не виживає.
zapl

4
@Selvin Я сподіваюся, що ви знаєте, що ви можете зробити BroadcastReciever слабкою посиланням на приймаючу діяльність і зробити її самореєстрацією, якщо вона осиротіла. Вам не потрібно відміняти його в режимі onPause, onDestroy чудово, поки ви не використовуєте BroadcastReceiver для збереження своєї активності в оперативній пам'яті. Ваш приклад показує погану практику, коли внутрішній клас просочує його зовнішній клас, він не є унікальним для BroadcastReceiver, і це те, що програмістам завжди доводиться захищати. Що стосується зміни GUI, ви можете зберігати стан, коли діяльність відновлена, вам не потрібно змінювати графічний інтерфейс.
ЙоханШогун

133

Я хотів би відповісти вичерпно.

  1. LocalbroadcastManager включений в android 3.0 і вище, тому вам потрібно використовувати бібліотеку підтримки v4 для ранніх версій. дивіться інструкції тут

  2. Створіть приймач широкомовної програми:

    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. Зареєструйте свій приймач у програмі onResume of aktivnosti, наприклад:

    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. скасувати реєстрацію приймача в режимі onPause:

    protected void onPause() {
      super.onPause();
      LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
    }
  5. Тепер, коли локальна трансляція буде надіслана від активності або послуги додатків, onReceive of onNotice буде викликаний :).

Редагувати: Ви можете прочитати повний підручник тут LocalBroadcastManager: Повідомлення програми внутрішньої програми


15
+1. якщо ваш транслятор у фрагменті, зареєструйте його, використовуючи LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onNotice);та LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onNotice);
скасуйте

3
Ви впевнені, що LocalBroadcastManager включений в Android 3.0 і новіших версій? Не можу знайти його ніде, окрім підтримки lib
men

5
як не дивно, LBM включений лише в бібліотеку підтримки.
Джефрі Блатман

1
super.onPause () має бути останньою заявою при перезаписі методу onPause. Скасуйте реєстрацію перед super.onPause, щоб уникнути непередбачуваної помилки
Thupten

2
Я вважаю, що ви можете перенести свій життєвий цикл на те, onStopщо в Android API 24+ з "Multi-Window / Split-View" (включено за замовчуванням в API 26+ affaicr) діяльність, з якою не взаємодіють, перебуває у призупиненому стані. Джерело: developer.android.com/guide/topics/ui/…
Martin Marconcini

45

Після закінчення отримання:

  • Перший реєстр LocalBroadcast Receiver
  • Потім обробити вхідні дані про наміри в 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 
              }
          }
      };

На кінці відправлення:

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

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

У моєму випадку лише тоді, коли я встановлював дію у намірі при надсиланні трансляції, інакше метод onReceive () ніколи не викликав ...
Акаш Бісарія

27

У Eclipse врешті-решт мені довелося додати бібліотеку сумісності / підтримки , клацнувши правою кнопкою миші на моєму проекті та вибравши:

Android Tools -> Add Support Library

Як тільки він був доданий, тоді я міг використовувати LocalBroadcastManagerклас у своєму коді.


Бібліотека сумісності Android


13

localbroadcastmanager застарілий, замість цього використовуйте реалізації шаблону, що спостерігається.

androidx.localbroadcastmanager застаріла у версії 1.1.0

Причина

LocalBroadcastManager- шина подій на всьому додатку та охоплює порушення рівня шару у вашій програмі; будь-який компонент може слухати події з будь-якого іншого компонента. Він успадковує непотрібні обмеження у випадку використання системи BroadcastManager; розробникам доводиться використовувати наміри, навіть якщо об'єкти живуть лише в одному процесі і ніколи не залишають його. З цієї ж причини він не дотримується функцій BroadcastManager.

Вони додають до заплутаного досвіду розробника.

Заміна

Ви можете замінити використання LocalBroadcastManagerіншими реалізаціями спостережуваного шаблону. Залежно від використання, підходящими варіантами можуть бути LiveDataабо реактивні потоки.

Перевага LiveData

Ви можете розширити LiveDataоб’єкт, використовуючи однотонний візерунок, щоб обернути системні сервіси, щоб вони могли ділитися у вашій програмі. В LiveDataоб'єкті підключається до системної службі один раз, а потім будь-якому спостерігачеві , який потребує ресурс може просто спостерігати за LiveDataоб'єкт.

 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()Метод передає фрагмент, який є екземпляром LifecycleOwner, в якості першого аргументу. Це означає, що цей спостерігач пов'язаний з Lifecycleоб'єктом, пов'язаним з власником, що означає:

  • Якщо об’єкт життєвого циклу не знаходиться в активному стані, спостерігач не викликається, навіть якщо значення змінюється.

  • Після знищення об'єкта життєвого циклу спостерігач автоматично видаляється

Той факт, що LiveDataоб'єкти усвідомлюють життєвий цикл, означає, що ви можете ділитися ними між різними видами діяльності, фрагментами та службами.


1
Ви маєте рацію щодо проникнення контекстів на весь світ, але я хотів би знати, що було б підходящою заміною, коли я хочу спілкуватися зі службою переднього плану, яка працює навіть без активності, але коли активність заходить, їм потрібно спілкуватися?
ateebahmed

2
Створіть однокласний клас з об’єктом LiveData та опублікуйте свої дані з сервісу. Після запуску активність може легко спостерігати LiveData без будь-якої шкоди. напр .: MyServiceData.getInstance (). getMyData (). спостерігати ...
Дариш

3
Я пропущу LocalBroadcastManager. Якщо це заплутало розробників в Google, можливо, їм потрібно припинити надмірну інженерію?
AFD

@Darish Чи був би цей однотонний клас рівносильним збереженню його в об’єкті Application? Чому такий вид глобальної держави в цих випадках не вважається поганою практикою?
xuiqzy

12

Як змінити глобальну трансляцію на LocalBroadcast

1) Створіть екземпляр

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);

2) Для реєстрації BroadcastReceiver

Замініть

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

З

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

3) Для надсилання широкомовного повідомлення

Замініть

sendBroadcast(intent);

З

localBroadcastManager.sendBroadcast(intent);

4) За відреєстрацію широкомовного повідомлення

Замініть

unregisterReceiver(mybroadcast);

З

localBroadcastManager.unregisterReceiver(mybroadcast);

Як я можу зареєструвати кілька IntentFilter ??
Парикшит Чалке

@ParikshitChalke: посилання
XMAN

6

Коли ви достатньо пограєте з LocalBroadcastReceiver, я запропоную вам спробувати Green Robot's EventBus - ви неодмінно зрозумієте різницю та корисність цього порівняно з LBR. Менше коду, що налаштовується на нитку приймача (UI / Bg), перевірку наявності приймачів, липких подій, подій можна використовувати як доставку даних тощо.


2

Приклад діяльності та служби, що реалізує LocalBroadcastManager, можна знайти в документах розробника . Я особисто вважав це дуже корисним.

РЕДАКТУВАННЯ: з цього часу посилання видалено з сайту, але дані такі: https://github.com/carrot-garden/android_maven-android-plugin-samples/blob/master/support4demos/src/com/ example / android / supportv4 / content / LocalServiceBroadcaster.java


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

0

Декларувавши його у вашому файлі AndroidManifest.xml з тегом (його також називають статичним)

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

Ви помітите, що оголошений вище приймач трансляції має властивість експортованого = "true". Цей атрибут повідомляє одержувачу, що він може приймати трансляції з-за меж програми.
2. Або динамічно, зареєструвавши екземпляр у registerReceiver (те, що відомо як зареєстрований контекст)

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

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

Існує три способи надсилання трансляцій:
Метод sendOriddBroadcast забезпечує пересилання трансляцій одночасно лише одному приймачу. Кожна трансляція може, у свою чергу, передавати дані тій, що йде за нею, або зупиняти поширення трансляції на наступні приймачі.
SendBroadcast схожий на метод, згаданий вище, з однією різницею. Усі приймачі широкомовної передачі отримують повідомлення і не залежать один від одного.
Метод LocalBroadcastManager.sendBroadcast надсилає трансляції лише приймачам, визначеним у вашій програмі, і не перевищує обсяг вашої програми.


-4

ми також можемо використовувати інтерфейс для того ж, що і BroadManger, тут я ділюсь тестовим кодом для BroadManager, але за інтерфейсом.

спочатку зробіть інтерфейс на зразок:

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

2-це перший клас, який потребує реалізації

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-ось другий клас, який реалізує той самий інтерфейс, метод якого викликає автоматично

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

тому таким підходом ми можемо використовувати інтерфейс, який функціонує так само, як і BroadManager.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.