Как использовать LocalBroadcastManager?

452

Как использовать / найти , LocalBroadcastManagerкак описано в Google Docs и службы вещания документ ?

Я пытался гуглить, но нет кода, с которого можно начать?

В документах говорится, что я должен использовать его, если я хочу делать внутреннюю трансляцию в процессе моего приложения, но я не знаю, где это искать.

Любая помощь / комментарий?

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

waqaslam
источник
Вакас, вы зарегистрировали получателя в манифесте. Если да, пожалуйста, дайте мне знать, как?
Мудасир
2
Я не думаю, что вам нужно регистрировать получателя для таких трансляций в манифесте, потому что если вы это сделаете, то этот получатель также будет прослушивать глобальные трансляции.
waqaslam
2
Правда. Тогда это означает, что я должен сделать это в коде, как указано в ответе ниже; LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("custom-event-name"));
Мудасир
2
LocalBroadcastManagerбыл объявлен устаревшим Я заменил свою на библиотеку EventBus, которая намного лучше, IMO.
Крис Б.

Ответы:

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! 
Shiki
источник
7
Спасибо. получил уже работает. но проблема, с которой я столкнулся, заключалась в том, чтобы получить класс LocalBroadcastManager. Поскольку это класс пакета поддержки, я не мог использовать его в своем обычном пакете, пока не добавил библиотеку совместимости из Android Tools. Как только его добавили, все прошло просто отлично. в любом случае, спасибо за ответ
waqaslam
195
пожалуйста, обратите внимание, что onDestroy()не гарантированно будет называться !!! Вы должны использовать onPause()(потому что только onPause()гарантировано) и onResume()(потому что это соответствует onPause())
18446744073709551615
5
Ребята, обратите внимание, что в документации Google теперь говорится о Activity после onPause (): Killable = Pre-HONEYCOMB Начиная с Honeycomb, приложение не находится в состоянии уничтожения, пока не будет возвращен его onStop ().
18446744073709551615
59
onDestroy()не проблема Случай, когда он не вызывается, - это когда приложение убивается, и не имеет значения, если вы не отмените регистрацию в этом случае, так как даже список зарегистрированных получателей не выживет.
Запл
4
@Selvin Надеюсь, вы знаете, что вы можете сделать BroadcastReciever слабо привязанным к получающему действию и отменить его регистрацию, если он потерян. Вам не нужно отменять регистрацию в onPause, с onDestroy все в порядке, если вы не используете свой BroadcastReceiver для сохранения своей активности в оперативной памяти. Ваш пример показывает плохую практику с внутренним классом, у которого утечка внешнего класса, он не уникален для BroadcastReceiver и является тем, что программисты всегда должны остерегаться. Что касается изменения GUI, вы можете сохранить состояние для возобновления активности, вам не нужно изменять GUI.
JohanShogun
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. Зарегистрируйте получателя в разделе Возобновление деятельности, например:

    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: передача сообщений внутри приложения

SohailAziz
источник
15
+1. если ваш Broadcast Receiver находится во фрагменте, зарегистрируйте его с помощью LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onNotice);и LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onNotice);
отмените
3
Вы уверены, что LocalBroadcastManager включен в Android 3.0 и выше? Не могу найти его нигде, кроме поддержки lib
mente
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/…
Мартин Маркончини,
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 () никогда не вызывается ...
Akash Bisariya
27

В Eclipse мне пришлось добавить библиотеку совместимости / поддержки , щелкнув правой кнопкой мыши по моему проекту и выбрав:

Android Tools -> Add Support Library

Как только он был добавлен, я смог использовать LocalBroadcastManagerкласс в своем коде.


Библиотека совместимости Android

waqaslam
источник
13

localbroadcastmanager устарел, вместо этого используйте реализации наблюдаемого шаблона.

androidx.localbroadcastmanager устарела в версии 1.1.0

причина

LocalBroadcastManager- шина событий всего приложения, охватывающая нарушения уровней в вашем приложении; любой компонент может прослушивать события от любого другого компонента. Он наследует ненужные ограничения варианта использования системы BroadcastManager; разработчики должны использовать Intent, даже если объекты живут только в одном процессе и никогда не покидают его. По этой же причине он не соответствует функциональности 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объекты учитывают жизненный цикл, означает, что вы можете делиться ими между несколькими действиями, фрагментами и службами.

Darish
источник
1
Вы правы в отношении утечки контекстов всему миру, но я хотел бы знать, что будет подходящей заменой, когда я хочу общаться с сервисом переднего плана, который работает даже без активности, но когда активность приходит, им нужно общаться?
Ateebahmed
2
Создайте одноэлементный класс с объектом LiveData и опубликуйте ваши данные из сервиса. Как только действие запускается, оно может легко наблюдать LiveData без какого-либо вреда. Например: MyServiceData.getInstance (). getMyData (). Наблюдать ...
Marish
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, я предлагаю вам попробовать EventBus от Green Robot - вы обязательно поймете разницу и полезность этого по сравнению с LBR. Меньше кода, настраиваемый для потока получателя (UI / Bg), проверка доступности получателей, липкие события, события могут быть использованы для доставки данных и т. Д.

Стан
источник
2

Пример Activity и Сервиса, реализующего LocalBroadcastManager, можно найти в документации для разработчиков. . Я лично нашел это очень полезным.

РЕДАКТИРОВАТЬ: с тех пор ссылка была удалена с сайта, но данные следующие: https://github.com/carrot-garden/android_maven-android-plugin-samples/blob/master/support4demos/src/com/ пример / Android / supportv4 / содержание / LocalServiceBroadcaster.java

nindalf
источник
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>

Вы заметите, что заявленный широковещательный приемник имеет свойство exported = «true». Этот атрибут сообщает получателю, что он может принимать широковещательные сообщения вне области приложения.
2. Или динамически путем регистрации экземпляра с помощью registerReceiver (так называемый зарегистрированный контекст)

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

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

Существует три способа отправки широковещательных
сообщений. Метод sendOrderedBroadcast обеспечивает одновременную отправку широковещательных сообщений только одному получателю. Каждая широковещательная рассылка может, в свою очередь, передавать данные той, которая следует за ней, или останавливать распространение широковещательной передачи для следующих получателей.
SendBroadcast похож на метод, упомянутый выше, с одним отличием. Все широковещательные приемники получают сообщение и не зависят друг от друга.
Метод LocalBroadcastManager.sendBroadcast отправляет широковещательные сообщения только получателям, определенным в вашем приложении, и не выходит за рамки вашего приложения.

Серой Григорян
источник
-4

мы также можем использовать интерфейс для того же, что и broadcastManger, здесь я делюсь кодом testd для broadcastManager, но по интерфейсу.

сначала создайте интерфейс вроде:

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

таким образом, при таком подходе мы можем использовать интерфейс, функционирующий так же, как broadcastManager.

падмендер сингх
источник