当前位置: 移动技术网 > 移动技术>移动开发>Android > android全方位解析BroadcastReceiver

android全方位解析BroadcastReceiver

2019年04月18日  | 移动技术网移动技术  | 我要评论

概念:

作为android的四大,相信很多人都知道broadcastreceiver,那什么是broadcastreceiver ? 直译是“广播接收者”,作用是接受发送过来的广播。那么是广播,举个例子:当我们上课,如果没有听到下课铃声,就不会出去教室,下课。当下课铃声后,我们就知道下课了,广播可以理解是一种消息的传递。再举个例子:我们开机时,会进行一个全局广播,消息是开机启动了,还有网络断开,链接到wifi,电量改变,系统都会作出反应。

android里面的broadcast其实跟我们生活中广播的意思很像,主要是用来消息通信(ipc),android的ipc基本都是binder来实现,而broadcastreceiver其实是对binder的一个封装,方便上层调用,在平时很多时候都是单进程但线程通信,很多人都会用observer或者使用eventbus等来完成功能,的确,它们在这场合效率和灵活性都非常高,但是,broadcastreceiver有自己独有的优势,第一是系统事件的监听,如:开机启动,电量变化;第二多进程通信,如现在多进程保活机制里面就用到了一些系统广播的监听。

原理:

android中的广播使用了设计模式中的观察模式:基于消息的发布/订阅事件模型,而这个模型有三个角色:1.广播接收者,2:广播发送者,3:消息中心(activity manager service),广播接收者通过binder机制在ams注册,广播发送者通过binder机制向ams发送广播,ams根据广播发送者要求,在已注册列表中寻找合适的广播接收者,通过intentfilter来进行刷选。ams将广播发送到合适的广播接收者相应的消息循环队列中,广播接收者通过消息循环拿到广播,并回调onreceiver().注意:广播发送者和广播接收者的执行是异步,发出去的广播不会关心有没有接收者接收,也不知道接收者什么时候能接受到。

 

具体使用:

1.动态注册

步骤:

1.通过继承broadcastreceiver建立动态广播接收器或者匿名内部类实现

2.实例化intentfilter对象

3.注册广播接收

4.移除广播接收器优化内存空间避免内存溢出

    broadcastreceiver mbroadcasrreceive = new broadcastreceiver() {
        @override
        public void onreceive(context context, intent intent) {
            string action = intent.getaction();
            if(action.equals(constant.login_success)){
                text_send.settext("收到动态广播");
            }
        }
    };


        intentfilter intentfilter = new intentfilter();
        intentfilter.addaction(constant.login_success);
        registerreceiver(mbroadcasrreceive,intentfilter);


    @override
    protected void onpause(){
        super.onpause();
        unregisterreceiver(mbroadcasrreceive);
    }


发送广播:

intent mintent = new intent(constant.login_success);
mintent.putextra("yanner","发送广播");
//发送广播
sendbroadcast(mintent);

这样动态方式就可以实现。注意:动态广播最好在activity的onresume()注册,onpause()注销。动态广播,有注册就必然有注销,否则会导致内存泄漏,重复注册和注销都是不允许的。为什么要在onpause()注销呢,因为onpause()在app死亡前一定会被执行,这样保证广播在app死亡前一定会被注销,从而防止内存泄漏。不在onstop()&ondestory()注销因为当系统如果内存不足时要回收activity占用的资源时,activity在执行完onpause()方法后就会被销毁,有些生命周期方法onstop(),ondestory()就不会执行。当再回到此activity时,是从oncreate方法开始执行。所以如果将广播的注销放在onstop(),ondestory()方法里的话,有可能在activity被销毁后还未执行onstop(),ondestory()方法,广播仍未注销,从而导致内存泄漏。,但是onpause()一定会被执行的。

2.静态注册

步骤:

1.继承broadcastreceiver,重写onreceive方法

public class staticreceiver extends broadcastreceiver {
    @override
    public void onreceive(context context, intent intent) {
        if(intent.getaction().equals(constant.register_success)){
            toast.maketext(context,"收到静态广播",toast.length_short).show();
        }
    }
}


2.在清单文件注册

 
        
            
                
                
            
        

注意这是自定义广播。

也可以使用系统广播:

以接收短信为例:

public class mybroadcastreceiver extends broadcastreceiver {
    //action 名称
    string sms_received = "android.provider.telephony.sms_received";
    @override
    public void onreceive(context context, intent intent) {
        if(intent.getaction().equals(sms_received)){
            //相关处理
        }
    }
}

在androidmanifest.xml中注册
 
        
            

        

注意还得要添加权限:


两种方式对比


注册方式 特点 使用场景
静态注册 常驻,不受任何组件的生命周期影响,应用程序关闭后,如果有信息广播里,程序依然会被系统调用,但是耗电站内存 需要时刻监听广播
动态注册 不是常驻,灵活,跟随组件的生命周期变化,组件结束 == 广播结束,在组件结束是,必须移除广播接收器 需要特定时刻监听广播




广播类型及广播的收发

普通广播:

发送一个广播,所以监听该广播的广播接收者都可以监听到该广播

异步广播:

当处理完之后的intent,依然存在,这时候registerreceiver(broadcastreceiver,intentfilter)还能收到他的值,直到把它去掉,不能将处理结果传递给下一个接收者,无法终止广播。

有序广播:

按照接收者的优先级顺序接收广播,优先级别在intent-filter中的priority中声明,-1000到1000之间,值越大,优先级越高,可以终止广播意图的继续传播,接收者可以篡改内容。

有序广播例子:

1.创建两个广播接收者:

public class firstreceiver extends broadcastreceiver {
    @override
    public void onreceive(context context, intent intent) {
        string msg = intent.getstringextra("msg");
        log.d("myfirstreceiver", msg);
        //将数据传输给下一个广播接收者
        setresultdata("this is the second msg from myfirstreceiver");
    }
}

 

public class secondreceiver extends broadcastreceiver {
    @override
    public void onreceive(context context, intent intent) {
        //获得上一个广播接收者传过来的数据
        string msg = getresultdata();
        log.d("mythirdreceiver", msg);
    }
}

2.在androidmanifest.xml中注册三个广播接收者

 

            

                
                
        

        
             
                 
                 
        

3.发送广播:
                intent mintent = new intent("orderbroadcast");
                mintent.putextra("yanner","发送广播");
                //发送广播
              //  sendbroadcast(mintent);
                sendorderedbroadcast(mintent,null);

打印log:

11-15 20:48:49.283 32069-32069/com.example.administrator.broadcastdemo d/11111: this is the first msg from myfirstreceiver
11-15 20:48:49.302 32069-32069/com.example.administrator.broadcastdemo d/1111: this is the second msg from myfirstreceiver


每个接收者都加了一个属性:priority,这个属性表示有序广播中的优先级,值越高表示优先级越高,当广播发出时,优先级最高的便会第一个接收到广播并拦截下来,然后继续往优先级低的传递下去。

总结:

广播接收者接收广播的顺序规则是:

按照priority属性值从大到小排序

priority属性一样时,动态注册广播优先

先接收的广播可以对广播进行拦截,后面接收的广播接收者不再接收到此广播

先接收的广播接收者可以对广播进行修改,后接收的广播接收者将接收到被修改后的广播

终止广播的方法是:abortbroadcast();

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网