Android四大组件之BroadcastReceiver知多少

说明:BroadcastReceiver——广播接收者,是Android四大组件之一,在实际的开发过程中BroadcastReceiver的应用场景非常多,本篇文章将详细讲解一下BroadcastReceiver,如果各位码友发现文中说明存在问题欢迎指正,CV操作请注明出处,谢谢!

1、定义说明。

    BroadcastReceiver即广播接收者,是Android四大组件之一,是一个全局的监听器。在Android中广播分为广播发送者和广播接收者,广播发送者(一般是其他的组件进行sendBroadcast操作),广播接收者(BroadcastReceiver)对发送出来Broadcast进行过滤、接收和响应。

2、使用场景。


    Android不同组件间的通信(包括进程内和进程之间,同一App和不同App)。
    与Android系统通信(如开机、网络状态、安装/卸载应用等)。


3、内部机制(原理)。

 

    设计模式:采用了观察者模式,基于消息的发布/订阅事件模型,使得广播的发送者和广播的接收者进行解耦。
    
    参与角色:广播(消息)发送者、广播(消息)接收者、AMS(ActivityManagerService)
    
    实现步骤概况:
    1、广播接收者通过Binder机制在AMS注册。
    2、广播发送者通过Binder机制在AMS发送广播。
    3、AMS根据广播发送者的要求,在注册列表中,根据IntentFilter /Permission查找目标广播接受者。
    4、AMS将广播发送给目标广播接收者的消息队列中。
    5、广播接收者通过消息队列获取消息,然后回调onReceive()。
    

4、使用介绍。


    4.1、广播的接收。


    广播接收者的使用大概分为三步:创建广播接收者、注册广播接收者、根据需求实现逻辑。


    4.1.1 、创建广播接收者。继承BroadcastReceivre,复写抽象方法onReceive()。


    public class XxxReceiver extends BroadcastReceiver {

        private static final String TAG = "XxxReceiver";

        public XxxReceiver() {
        }

        @Override
        public void onReceive(Context context, Intent intent) {
        //处理业务逻辑等,如发送Notification、启动Service等
            
        }
    }
    注意:onReceive运行在UI线程中,因此,onReceive()方法不能执行耗时操作,否则将导致ANR
    另外不要在此有开启子线程的操作,会造成内存泄漏,如果需要请采用其他方式或者IntentService


    4.1.2 、注册广播接收者(Android 8.0大部分静态注册广播失效,仅剩下较少的系统广播可以静态注册)。


     1、静态注册,即在清单文件中为BroadcastReceiver进行注册,使用<receive >标签声明,并在标签内<intent-filter >标签设置过滤器。
     这种形式的 BroadcastReceiver 的生命周期伴随着整个应用,如果这种方式处理的是系统广播,那么不管应用是否在运行,该广播接收器都能接收到该广播
     <receiver android:name=".XxxReceiver">
            <intent-filter>
                <action android:name="com.example.leisure.yyy" />
                <!--过滤属性,只有具有该属性的广播才会被接收-->
            </intent-filter>
        </receiver>
     <XxxReceiver 
        广播接收者为四大组件之一,也具有下边的较为常用的属性
         android:exported="true"<!--外部应用是否可以调用,默认为true,如果不对外开放,建议false-->
         android:permission=""<!--具有相应权限的广播发送者发送的广播才能被此BroadcastReceiver所接收-->
         android:process=""<!--指定进程-->
         android:enabled=""<!--能否接收其他App的发出的广播-->


     2、动态注册。即在代码中定义并设置好一个IntentFilter对象,然后在需要注册的地方调用Context.registerReceiver()方法,调用Context.unregisterReceiver()可以取消注册。
        @Override
        public void onCreate() {
            super.onCreate();//注册广播
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction("com.example.leisure.yyy");//
            receiver = new XxxReceiver();
            registerReceiver(receiver, intentFilter);
            
        }

        @Override
        public void onDestroy() {
            super.onDestroy();//取消注册广播
            unregisterReceiver(receiver);
        }
        注意:动态广播的注册和取消注册须要成对出现。如果Activity/Fragment中建议在onResume()注册、onPause()注销广播因为onPause()在App死亡前一定会被执行,从而保证广播在App死亡前一定会被注销,从而防止内存泄露。除非必要不建议在onCreate()/onDestory() 或 onStart()/onStop()注册、注销,因为当系统因为内存不足(如优先级更高的应用需要内存)要回收Activity占用的资源时,Activity在执行完onPause()方法后就会被销毁,有些生命周期方法onStop(),onDestory()就不会执行。
当再回到此Activity时,是从onCreate方法开始执行,造成内存泄漏。

        

4.2、广播的发送。
    

4.2.1、广播的分类,可分为5种:Normal Broadcast、System Broadcast、Sticky Broadcast、Local Broadcast。


        1、普通广播(Normal Broadcast)。
        最为常用的广播,一般需要添加action,声明了对应的action的广播接收者才能收到广播,即onReceive()回调。如果添加了权限,则广播接收者也需要在注册的时候明确权限。
        
        Intent intent = new Intent();
        //对应BroadcastReceiver中intentFilter的action,
        intent.setAction("com.example.leisure.yyy");
        //发送广播
        sendBroadcast(intent);
        
        2、系统广播(System Broadcast)。
        系统广播,不需要app去发送,由系统根据情况自动发送,app只负责接收(如果需要)。
        
        3、有序广播(Ordered Broadcast)。发送出去的广播被广播接收者按照先后顺序接收,有序是针对广播接收者而言的。
         广播接受者接收的顺序规则是按照Priority属性值从大到小排序(同一Priority,动态注册的广播优先级大于静态注册的广播);
         先接收的广播接收者可以对广播进行拦截,小优先级的广播接收者将无法收到该广播;
         先接收的广播接收者可以对广播进行修改,小优先级的广播接收者将接收到被修改后的广播。
         
        示例:
        
        Intent intent = new Intent("com.receiver.leisure.common");
        intent.putExtra("xxx", "有序广播");
        sendOrderedBroadcast(intent, null);//发送有序广播
        
        //此处忽略了注册过程。
        
        public class OrderReceiverXxx extends BroadcastReceiver {//第一优先级

            public OrderReceiverXxx() {
            }

            @Override
            public void onReceive(Context context, Intent intent) {

                //取出Intent当中传递来的数据
                String msg = intent.getStringExtra("xxx");
                //向下一优先级的Receiver传递数据
                Bundle bundle = new Bundle();
                bundle.putString("yyy", "xxx修改了广播");
                setResultExtras(bundle);
            }
        }
        
        public class OrderReceiverYyy extends BroadcastReceiver {//第二优先级

            public OrderReceiverYyy() {
            }

            @Override
            public void onReceive(Context context, Intent intent) {
                //取出上一优先级的Receiver传递来的数据
                String data = getResultExtras(true).getString("yyy");

                //拦截广播
                abortBroadcast();
            }
        }
        
        public class OrderReceiverZzz extends BroadcastReceiver {//第三优先级

            public OrderReceiverZzz() {
            }

            @Override
            public void onReceive(Context context, Intent intent) {
                //收不到广播了
            }
        }
        
        4、粘性广播(Sticky Broadcast)。Android5.0(API 21)中已经失效,可忽略。
        
        5、本地广播(Local Broadcast)。
    由于Android中的广播可以跨进程(App)通信,不同的App注册的广播intent-filter可能会相同,也存在其他App根据intent-filter针对性的恶意发送某些广播造成安全或者效率问题。
    Android内提供了本地广播,广播的发送者和接收者都同属于一个App,提高了效率和安全性。
    针对普通广播效率和安全性的问题,一般有两种方式:
        1、注册广播时候将exported属性设置为false;增设相应权限permission,用于权限验证;发送广播指定包名。
        2、建议使用本地广播的形式。
        本地广播是使用LocalBroadcastManager来对广播进行管理,和普通广播存在注册、发送的方式的细微差别,除此之外都一样。

        LocalBroadcastManager.getInstance(this).registerReceiver(BroadcastReceiver, IntentFilter)
        注册Receiver

        LocalBroadcastManager.getInstance(this).unregisterReceiver(BroadcastReceiver);
        注销Receiver

        LocalBroadcastManager.getInstance(this).sendBroadcast(Intent)
        发送异步广播

        LocalBroadcastManager.getInstance(this).sendBroadcastSync(Intent)
        发送同步广播

        
5、注意事项。


1、不同注册方式的广播接收器回调OnReceive(Context context,Intent intent)中的context返回值是不一样的,静态注册的广播是ReceiverRestrictedContext;动态注册的广播是Activity Context;本地广播是Application Context。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值