Android组件Broadcast Receiver学习

Android大量使用了Broadcast Receiver来广播系统事件,如网络连接、扩展dock状态及来电的变化。

一、注意:

android 中service和broadcastreceiver都是运行在主UI线程中,如果在他们中执行耗时操作,若果操作持续的时间超过android平台的约定,那么android平台会认为该程序出现异常,从而抛出ANR异常。如果在onReceive()的处理中,用户进行了UI触发,将可能引发ANR异常,不过和activity的时间限制不同,receiver在10秒而非5秒后触发ANR。

处理耗时的Broadcast Receiver时,一般采用的做法是将其置于一个Service中:(也可以通过在程序中使用registerReceiver(receiver, filter, broadcastPermission, scheduler)方法中的最后一个参数指定要运行的广播接收器的线程。

1、在广播receiver的onReceive()中获取static的wake lock,静态是为了在广播接收器和service之间通信。因为service没有什么其他法将一个wake lock对象传递到service中。

2、开启local service使得进程不被终结。

3、在service中开启一个worker线程来进行处理。

4、当worker线程处理完,要通知service结束,可以直接stop(),或者通过Handler在主线程中结束service。

5、service要关闭静态的wake lock


二、BrocastReceiver用法:

1、继承BroadcastReceiver类,重写其onReceive函数:

/** 自定义BroadcastReceiver,只需重写其onReceive函数即可**/
public class TestBroadcastReceiver extends BroadcastReceiver{   
    public static final String ACTION = "com.TestBroadcastReceiver";
 
    /** receiver接收到消息后的响应*/
    @Override
    public void onReceive(Context context, Intent intent) {
        // @value String TEXT_EXTRA = "TEXT_EXTRA";
        String reString = intent.getStringExtra(MainActivity.TEXT_EXTRA);
        Toast.makeText(context, reString, Toast.LENGTH_SHORT).show();
    }
}

2、可以选择在代码中动态注册BroadcastReceiver,也可以在Manifest中注册全局BroadcastReceiver         

两种注册方式的区别:
1)在manifest中注册的receiver总是活动的,当应用程序被终止或者未启动时,也可以接收Broadcast Intent;
2)代码中注册的receiver通常是影响特定Activity的UI,而且该receiver只会在包含它的应用程序组件运行时才会响应Broadcast Intent;一般较好的注册实现方式为在onResume()中注册,在onPause()中注销。

(1)在manifest中注册receiver

<!-- 注意要放在application中 -->
<!-- 在manifest中注册receiver-->
<receiver android:name=".TestBroadcastReceiver"
      android:permission="TestBroadcastReceiver">
    <intent-filter>
        <action android:name="com.TestBroadcastReceiver"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</receiver>

(2)在Activity代码中动态注册BroadcastReceiver,较好的实践方式是在onResume中注册,在onPause中注销。

    private IntentFilter intentFilter;
    private TestBroadcastReceiver receiver;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       
        intentFilter = new IntentFilter(TestBroadcastReceiver.ACTION);
        receiver = new TestBroadcastReceiver();
    }
   
    @Override
    public void onResume(){
        super.onResume();
        // 注册receiver
        registerReceiver(receiver, intentFilter);
    }
   
    @Override
    public void onPause(){
        // 注销receiver
        unregisterReceiver(receiver);
        super.onPause();
    }

3、发送Intent消息

    // 发送Intent信息,以便BrocastReceiver接收
    Intent intent = new Intent(TestBroadcastReceiver.ACTION);
    // @value String ACTION = "com.TestBroadcastReceiver";
    intent.putExtra(TEXT_EXTRA, "Send Message");
    // @value String TEXT_EXTRA = "TEXT_EXTRA"
    // 发送Intent消息
    sendBroadcast(intent);


三、Local Broadcast Manager(局部广播管理器)

Local Broadcast Manager包含在Android Support Library中,用于简化注册Brocast Intent,以及在应用程序内的组件之间发送Broadcast Intent
的工作。因为局部广播的作用域要稍小一点,所以使用Local Broadcast Manager比全局广播更加高效,也更加安全。

用法与代码中注册的BroadcastReceiver大致相同:

    // 单例模式获取实例
    LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
   
    // 自定义BroadcastReceiver
    BroadcastReceiver broadcastReceiver = new BroadcastReceiver(){
        @Override
        public void onReceive(Context context, Intent intent) {
       
        }};
  
    // 注册receiver
    lbm.registerReceiver(broadcastReceiver, new IntentFilter(TestBroadcastReceiver.ACTION));
    // 发送Intent消息
    lbm.sendBroadcast(new Intent(TestBroadcastReceiver.ACTION));
    // 注销receiver
    lbm.unregisterReceiver(broadcastReceiver);


四、相关面试题

1、注册广播接收者两种方式的区别,及优缺点

答:首先写一个类要继承BroadcastReceiver

第一种:在清单文件中声明receiver

第二种使用代码进行注册registerReceiver


两种注册类型的区别是:

1)第一种是常驻型(静态注册),也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。

2)第二种不是常驻型广播(动态注册),也就是说广播跟随程序的生命周期。


优缺点:

动态注册优点:在 Android 的广播机制中,动态注册的优先级是要高于静态注册优先级的,因此在必要的情况下,我们是需要动态注册广播接收器的。

静态注册优点:动态注册广播接收器还有一个特点,就是当用来注册的 Activity 关掉后,广播也就失效了。同时反映了静态注册的一个优势,就是无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器就是打开着的。


2Android引入广播机制的用意

答:a:MVC的角度考虑(应用程序内

    其实回答这个问题的时候还可以这样问,android为什么要有那4大组件,现在的移动开发模型基本上也是照搬的web那一套MVC架构,只不过是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的MVC架构,它们之间有时候是一种相互依存的关系,有时候又是一种补充关系,引入广播机制可以方便几大组件的信息和数据交互。 

    b:程序间互通消息(例如在自己的应用程序内监听系统来电

c:效率上(参考UDP的广播协议在局域网的方便性

d:设计模式上(反转控制的一种应用,类似监听者模式)

 

3、解释一下activity、 intent intent filterserviceBroadcaseBroadcaseReceiver 

答:

一个activity呈现了一个用户可以操作的可视化用户界面 

一个service不包含可见的用户界面,而是在后台运行,可以连接到一个正在运行的服务中,连接后,可以通过服务中暴露出来的借口与其进行通信 

一个broadcast receiver是一个接收广播消息并作出回应的componentbroadcast receiver没有界面 

content provider在接收到ContentResolver的请求时被激活。 

activity, servicebroadcast receiver是被称为intents的异步消息激活的。 


一个intent是一个Intent对象,它保存了消息的内容。对于activityservice来说,它指定了请求的操作名称和待操作数据的URI 

Intent对象可以显式的指定一个目标component(组件)。如果这样的话,android会找到这个component(基于manifest文件中的声明)并激活它。但如果一个目标不是显式指定的,android必须找到响应intent的最佳component。 

它是通过将Intent对象和目标的intent filter相比较来完成这一工作的。一个componentintent filter告诉androidcomponent能处理的intentintent filter也是在manifest文件中声明的。 


你可能感兴趣的:(Android组件Broadcast Receiver学习)