Android通信方案LiveDataBus笔记

一:通信方案总结,对比

1,Handler     优点:系统原生,能实现线程间通信;  缺点:高耦合,不利于维护,容易导致内存泄露和空指针;

2,Boadcast  优点:简单;  缺点:性能差,传播数据有限。打乱代码的执行逻辑;

3,Interface    优点:速度快,容易理解; 缺点:实现复杂,不利于维护;

4,rxBus         优点:效率高,无内存泄露; 缺点:基于rxjava,学习成本高且依赖包太大,rxjava2.2M;

5,EventBus  优点:使用简单;    缺点:混淆问题,无法感知组件生命周期,实现复杂;

6,LiveDataBus 优点:实现简单,代码量少,官方提供稳定的依赖代码,感知组件(Acitivity,Fragment,Servcie等)生命周期,不存在内存泄露

二:LiveDataBus结构图

1,什么是发布-订阅模式?

定义:这个模式用来作为中间人,一个把发布者和订阅者架接在一起的代理。

2,什么是LiveData?

定义:一个数据持有类,持有数据并且这个数据可以被观察被监听,和其他observable不同的是,它是和Lifecycle是绑定的,在生命周期内使用有效,减少内存泄露和引用问题;

3,如何构建LiveDataBus;

LiveDataBus的设计和架构

LiveDataBus的组成

  • 消息
    消息可以是任何的Object,可以定义不同类型的消息,如Boolean、String。也可以定义自定义类型的消息。

  • 消息通道
    LiveData扮演了消息通道的角色,不同的消息通道用不同的名字区分,名字是String类型的,可以通过名字获取到一个LiveData消息通道。

  • 消息总线
    消息总线通过单例实现,不同的消息通道存放在一个HashMap中。

  • 订阅
    订阅者通过getChannel获取消息通道,然后调用observe订阅这个通道的消息。

  • 发布
    发布者通过getChannel获取消息通道,然后调用setValue或者postValue发布消息。

三:LiveData的优点

  • UI和实时数据保持一致,因为LiveData采用的是观察者模式,这样一来就可以在数据发生改变时获得通知,更新UI。

  • 避免内存泄漏,观察者被绑定到组件的生命周期上,当被绑定的组件销毁(destroy)时,观察者会立刻自动清理自身的数据。

  • 不会再产生由于Activity处于stop状态而引起的崩溃,例如:当Activity处于后台状态时,是不会收到LiveData的任何事件的。

  • 不需要再解决生命周期带来的问题,LiveData可以感知被绑定的组件的生命周期,只有在活跃状态才会通知数据变化。

  • 实时数据刷新,当组件处于活跃状态或者从不活跃状态到活跃状态时总是能收到最新的数据。

  • 解决Configuration Change问题,在屏幕发生旋转或者被回收再次启动,立刻就能收到最新的数据。

package test.pvj.com.livedatabusdemo;

import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.Observer;
import android.os.Looper;
import android.support.annotation.NonNull;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

//SDK 25版本及以上
// def lifecycle_version = "1.1.1"
//implementation "android.arch.lifecycle:extensions:$lifecycle_version"
public class LiveDataBus {

    private static LiveDataBus mInstance;
    private static Map<String, MyMutableLiveData> mLiveDatas = new HashMap<>();

    private LiveDataBus() {

    }

    public static LiveDataBus get() {
        if (mInstance == null) {
            synchronized (LiveDataBus.class) {
                if (mInstance == null) {
                    mInstance = new LiveDataBus();
                }
            }
        }
        return mInstance;
    }

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

    public <T> void post(String key, T t){
        if(Looper.getMainLooper() == Looper.myLooper()){
            with(key).setValue(t);
        }else {
            with(key).postValue(t);
        }
    }

    public static class MyMutableLiveData<T> extends MutableLiveData {
        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
            super.observe(owner, observer);
            try {
                hook(observer);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void hook(@NonNull Observer<T> observer) throws Exception {
            //get wrapper's version
            Class<LiveData> classLiveData = LiveData.class;
            Field fieldObservers = classLiveData.getDeclaredField("mObservers");
            fieldObservers.setAccessible(true);
            Object objectObservers = fieldObservers.get(this);
            Class<?> classObservers = objectObservers.getClass();
            Method methodGet = classObservers.getDeclaredMethod("get", Object.class);
            methodGet.setAccessible(true);
            Object objectWrapperEntry = methodGet.invoke(objectObservers, observer);
            Object objectWrapper = null;
            if (objectWrapperEntry instanceof Map.Entry) {
                objectWrapper = ((Map.Entry) objectWrapperEntry).getValue();
            }
            if (objectWrapper == null) {
                throw new NullPointerException("Wrapper can not be bull!");
            }
            Class<?> classObserverWrapper = objectWrapper.getClass().getSuperclass();
            Field fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion");
            fieldLastVersion.setAccessible(true);
            //get livedata's version
            Field fieldVersion = classLiveData.getDeclaredField("mVersion");
            fieldVersion.setAccessible(true);
            Object objectVersion = fieldVersion.get(this);
            //set wrapper's version
            fieldLastVersion.set(objectWrapper, objectVersion);
        }
    }
}

注册订阅

LiveDataBus.get()
        .with("key_test", String.class)
        .observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable String s) {
            }
        });

发送消息:

LiveDataBus.get().with("key_test").setValue(s);

更详细的参考链接文章:https://tech.meituan.com/2018/07/26/android-livedatabus.html

里面的github demo例子有点多,容易让开始看的人迷糊。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Framework核心知识笔记是一本介绍Android Framework核心知识的pdf文档。Android Framework是Android系统的基础,它包含了一系列的类库和API,为开发Android应用程序提供了基本的功能和特性。 这本笔记首先介绍了Android Framework的概述,包括其组成部分和架构。然后详细讲解了Android四大组件(Activity、Service、Broadcast Receiver和Content Provider)的实现原理和使用方法。这些组件是Android应用程序的基本构建模块,理解它们的工作原理对于开发高质量的Android应用程序至关重要。 接着,笔记Android Framework中的UI设计进行了深入讲解。它介绍了View和ViewGroup的层次结构以及布局管理器的使用方法,帮助开发者实现灵活且具有吸引力的用户界面。此外,它还讨论了Android的绘图机制和动画效果,使开发者能够创建更加生动和吸引人的界面。 另外,笔记还包含了关于Android Framework中的数据存储和访问的内容。它介绍了SharedPreferences、SQLite数据库以及Content Provider等数据持久化的方法,帮助开发者存储和管理应用程序的数据。 此外,笔记还涵盖了与Android Framework相关的其他主题,如网络通信、多媒体处理、传感器和位置服务等。它们帮助开发者实现更多样化和功能强大的应用程序。 总结来说,Android Framework核心知识笔记是一本全面介绍Android Framework的教程,帮助开发者掌握Android应用程序开发的基本技能。对于想要成为Android开发专家的人来说,这是一本不可或缺的参考资料。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值