如何使用LocalBroadcastManager?


452

如何LocalBroadcastManager按照google文档服务广播文档中的说明使用/定位?

我试图用Google搜索它,但是没有可用的代码开头吗?

这些文档说,如果我想在应用程序的过程中进行内部广播,则应该使用它,但我不知道在哪里寻找它。

有帮助/意见吗?

更新:我知道如何使用广播,但是不知道如何LocalBroadcastManager在我的项目中使用广播。


Waqas,您是否已在清单中注册接收器。如果是,请让我知道如何?
Mudassir 2012年

2
我认为您不需要在清单中注册此类广播的接收方,因为如果您这样做,那么该接收方也将监听全局广播。
waqaslam'4

2
真正。这意味着,我必须按照下面的答案中的代码进行操作;LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("custom-event-name"));
Mudassir

2
LocalBroadcastManager已不推荐使用。我用EventBus库替换了我的,后者好得多了,imo。
Kris B

Answers:


861

无论如何,我会回答。以防万一有人需要它。

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单击按钮时,mMessageReceiverin 都会广播并接收一个Intent 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 2012年

195
请注意,onDestroy()不保证会被调用!!!您必须使用onPause()(因为仅能onPause()保证)和onResume()(因为它是的匹配项onPause()
18446744073709551615 2012年

5
亲朋好友,请注意Google文档现在对onPause()之后的活动说了什么:Killable = Pre-HONEYCOMB 从Honeycomb开始,直到其onStop()返回之前,应用程序才处于可杀死状态。
18446744073709551615 2013年

59
onDestroy()没问题 不调用该应用程序的情况是该应用程序被终止时,在这种情况下您是否不注销也没有关系,因为即使已注册的接收者列表也无法幸免。
zapl 2014年

4
@Selvin我希望您知道,您可以使BroadcastReciever弱引用接收活动,并使其成为孤立状态(如果是孤立的话)。您不需要在onPause上注销它,只要您不使用BroadcastReceiver将活动保留在RAM中,onDestroy就可以了。您的示例显示了一个不好的做法,即内部类泄漏了外部类,这不是BroadcastReceiver独有的,程序员必须始终注意这一点。至于修改GUI,您可以存储恢复活动的状态,而不必修改GUI。
JohanShogun,2015年

132

我想全面回答。

  1. android 3.0及更高版本中包含LocalbroadcastManager,因此对于早期版本,您必须使用支持库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中注册您的接收者,例如:

    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. 现在,每当从应用程序的活动或服务发送本地广播时,就会将onNotice的onReceive称为:)。

编辑:您可以在此处阅读完整的教程LocalBroadcastManager:应用程序内消息传递


15
+1。如果您的广播接收器是一个片段,请使用LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onNotice);进行注册,并使用LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onNotice);
PeteH

3
您确定LocalBroadcastManager包含在Android 3.0及更高版本中吗?除了支持lib,在任何地方都找不到它
mente

5
奇怪的是,LBM仅包含在支持库中。
Jeffrey Blattman 2013年

1
覆盖onPause方法时,super.onPause()应该是最后一个语句。在super.onPause之前取消注册以避免不可预测的错误
Thupten

2
我相信您可能希望将生命周期转移到,onStop因为在具有“多窗口/拆分视图”功能的Android API 24+(默认在API 26+功能中启用)中,未与之交互的活动处于暂停状态。来源:developer.android.com/guide/topics/ui/...
马丁Marconcini

45

在接收端:

  • 首先注册LocalBroadcast接收器
  • 然后在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相容性程式库


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?
Parikshit Chalke,

@ParikshitChalke:链接
XMAN

12

不建议使用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与所有者关联的对象,这意味着:

  • 如果Lifecycle对象未处于活动状态,则即使值更改也不会调用观察者。

  • 生命周期对象销毁后,观察者将自动删除

LiveData对象具有生命周期感知这一事实意味着您可以在多个活动,片段和服务之间共享它们。


1
您将上下文泄露给整个世界是正确的,但是我想知道什么是当我想要从即使没有活动就运行的前台服务进行通信时的合适替代方法,但是当活动进入时,他们需要进行通信吗?
ateebahmed

1
使用LiveData对象创建一个单例类,然后从服务中发布数据。活动启动后,活动可以轻松观察LiveData,而不会造成任何伤害。例如:MyServiceData.getInstance()。getMyData()。observe ...
Dariish

3
我会想念LocalBroadcastManager。如果这让Google开发人员感到困惑,也许他们需要停止过度设计吗?
AFD

@Darish此单例类是否等效于将其存储在Application对象中?为什么在这种情况下这种全球状态不被视为不良做法?
xuiqzy

6

当您在LocalBroadcastReceiver上玩足够的游戏时,我建议您尝试一下Green Robot的EventBus-与LBR相比,您一定会意识到它的区别和实用性。较少的代码,可以自定义接收方的线程(UI / Bg),检查接收方的可用性,粘性事件,事件可以用作数据传递等。




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>

您会注意到上面声明的广播接收器具有export =“ 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相同的接口,在这里我通过接口共享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相同的接口。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.