Android消息机制之LiveDataBus

LiveDataBus基础

LiveDataBus具有生命周期感知和Lifecycle绑定,不需要注册和反注册,没有内存泄漏风险
LiveDataBus实现简单相对EventBus的复杂实现,LiveDataBus只需要一个类
LiveDataBus减小APK包大小LiveDataBus只依赖Android官方组件LiveData
LiveDataBus依赖方支持更好相对RxBus依赖于RxJava,LiveDataBus只依赖于官方组件

 

 

 

 

 

 观察者模式和发布订阅模式有什么区别?

  • LiveData采用观察者模式,观察者和被观察者互相可见,被观察者通知观察者进行改变,例如长途汽车上乘务员通知指定乘客到站。
  • LiveDataBus基于LiveData组件,采用发布订阅模式,观察者和被观察者互相不可见。被观察者会发出广播,观察者只会对自己订阅的广播做出反应。例如高铁动车上的广播到站。

数据结构

LiveDataBus采用一个map进行储存键值对,其中Key为String类型,决定了发布者发布到哪个消息通道、而订阅者通过这个key找到其订阅的通道。

with方法是从map里返回一个具体LiveData对象,即返回一个消息通道。

消息通道即为value,是一个LiveData<Object>的对象。本文使用LiveData的子类MutableLiveData简化发布订阅操作。Object就是消息的类型,在新建LiveData对象时设置。

使用双重校验的单例模式,保证只有一个map,即只有一条消息总线。

 

public final class LiveDataBus {
    private static Map<String , MutableLiveData<Object>> map = null;

    public LiveDataBus() {
        map = getInstance();
    }

    private static class SingleHolder {
        private static final LiveDataBus DATA_BUS = new LiveDataBus();

    }

    public static LiveDataBus get(){
        return SingleHolder.DATA_BUS;
    }

    private static Map<String ,  MutableLiveData<Object>> getInstance(){
        if (map == null){
            synchronized (LiveDataBus.class){
                if (map == null){
                    map = new HashMap<>();
                    return map;
                }
            };
        }
        return  map;
    }

    public <T>  MutableLiveData<T> with(String key, Class<T> type){
        if (!map.containsKey(key)){
            map.put(key, new  MutableLiveData<Object> ());
        }
        return (MutableLiveData<T>)map.get(key);
    }

    public MutableLiveData<Object> with(String key){
        return with(key, Object.class);
    }
}

 

订阅方法

在map中通过key获取订阅对象的消息通道LiveData,并设置观察的消息类型,再实现observe接口,具体执行订阅到消息后的事件处理。

LiveDataBus.get().
                with("Main A", String.class)
                .observe(this,
 (Observer<String>) s -> 
Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show());

发送消息方法

postValue()用于子线程中,setValue()用于主线程中,方法内容是向LiveData传递一个消息。

//子线程使用
LiveDataBus.get().with("Child B").postValue("Child B msg");
//主线程使用
LiveDataBus.get().with("Main A").setValue("Main B msg");

完整流程

        LiveDataBus.get()
                .with("Main A", String.class)
                .observe(this,  s -> Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show());

        btn2.setOnClickListener(view ->
                LiveDataBus.get().with("Main B").setValue("Main A msg"));

 activity启动后会自动订阅“Main A”的消息通道;用户点击按钮btn2后会发送消息”Main A ms“到“Main A”的消息通道中,之后订阅者收到消息后会在activity活跃时执行onchange方法(由lamda表达式简化)。

 

 

总结 

用map可以模拟总线,每一个键值对即对应着一条支线。

追踪组件生命周期可以避免内存泄漏。

例如handler会持有外部类activity的引用,在activity结束后handler仍在处理自己的事件,即造成内存泄漏。

 

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值