LiveDataBus核心原来如此简单

Android Architecture Components 系列目录

  1. LiveData原理深入浅出,透过源码看本质
  2. LiveDataBus框架抽丝剥茧后,原来如此简单
  3. Android Room数据库,用过你才知道好

LiveData通过源码看本质

博客创建时间:2021.01.27
博客更新时间:2021.02.26

以Android studio build=4.1.1,gradle=6.5,SdkVersion 30来分析讲解。如图文和网上其他资料不一致,可能是别的资料版本较低而已


前言

在博客《LiveData原理深入浅出,透过源码看本质 》中通过源码的详细分析,已经说明了LiveData的原理和使用流程。

本篇博客通过自己对LiveData的理解,封装名为LiveDataBus的通信框架。框架为纯Kotlin代码框架,其实框架实现很简单,原理完全基于LiveData。名字虽与网络上的LiveDataBus一样,功能也基本一致,但其内涵完全不一样,且看我一一剖析。

使用介绍

使用非常简单步骤分为:1.注册监听;2.数据更新后发布;3.收更新数据进行处理;4.注销监听。 使用流程如下代码,超级简单。

public class MainActivity extends AppCompatActivity {
    
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.btnSendOne).setOnClickListener(v ->
                // 2.数据更改后,数据发布
                LiveDataBus.sendLiveString("单次点击")
        );

        findViewById(R.id.btnMultiData).setOnClickListener(v -> {
    
    
                    new Thread(() -> {
    
    
                        int count = 0;
                        while (count < 100) {
    
    
                            LiveDataBus.sendLiveString("复数点击");
                            try {
    
    
                                Thread.sleep(400);
                                count++;
                            } catch (InterruptedException e) {
    
    
                                e.printStackTrace();
                            }
                        }
                    }).start();
                }
        );

        //1.注册监听 observeForever(observer)方式注册
        LiveDataBus.observeForever("LIVE_EVENT_BUS_COMMON_LIVE_STRING", observer);
    }

    private final Observer<String> observer = s ->
            // 3. 数据处理
            Log.i("111111", s);
    @Override
    protected void onDestroy() {
    
    
        super.onDestroy();
        //4.注销观察
        LiveDataBus.removeObserver("LIVE_EVENT_BUS_COMMON_LIVE_STRING", observer);
    }
}

注意:

  1. 观察者的注册方式有两种observe(owner, observer)和observeForever(observer)。如果采用了observe(owner, observer)方式注册,则不必进行第4步注销观察,当Activity处于DESTORY状态时observer会自动注销观察。
     //1. 注册监听 observe(owner, observer)方式注册
        LiveDataBus.observe(LiveDataBus.LIVE_EVENT_BUS_COMMON_LIVE_STRING, this, observer);
        //1.注册监听 observeForever(observer)方式注册
        LiveDataBus.observeForever("LIVE_EVENT_BUS_COMMON_LIVE_STRING", observer);
  1. 数据更新发布可以在UI线程中执行,也可在非UI线程中执行
        findViewById(R.id.btnSendOne).setOnClickListener(v ->
                // 2.数据更改后,数据发布
                LiveDataBus.sendLiveString("UI线程中发布数据更新")
        );

        findViewById(R.id.btnMultiData).setOnClickListener(v -> {
    
    
                    new Thread(() -> {
    
    
                        int count = 0;
                        while (count < 100) {
    
    
                            LiveDataBus.sendLiveString("非UI线程中发布数据更新");
                            try {
    
    
                                Thread.sleep(400);
                                count++;
                            } catch (InterruptedException e) {
    
    
                                e.printStackTrace();
                            }
                        }
                    }).start();
                }
        );

结构分析

框架简单只有LiveDataBus 、 IConst、 LiveEventBus、 LiveDataReceiver四个文件,其核心是LiveEventBus类,对外暴露开放的操作类为LiveDataBus,其他两个类是辅助类文件
在这里插入图片描述
LiveEvent

LiveData 包装类,是事件真正运行操作的执行类,每个LiveEvent都必须包含一个MutableLiveData,同样数据的通行采用了观察者模式,所以LiveEvent中的方法实际分为两类,观察者的注册解绑和数据的更新发布。因LiveData中的相关方法都必须执行在主线程中,所以LiveEvent的调用者在执行时需要判断线程是否为主线程,确保LiveData的调用在主线程中。

扫描二维码关注公众号,回复: 13145363 查看本文章

1)观察者注册解绑
通信框架基于LiveData,自然含有其重要的三个注册及解绑的方法observe、observeForever、removeObserver。

       /**
         * 注册一个Observer,生命周期感知,自动取消订阅
         */
        fun observe(owner: LifecycleOwner, observer: Observer<T>) {
    
    
            if (isMainThread) {
    
    
                liveData.observe(owner, observer)
            } else {
    
    
                mainHandler.post {
    
     liveData.observe(owner, observer) }
            }
        }

        /**
         * 注册一个Observer
         */
        fun observeForever(observer: Observer<T>) {
    
    
            if (isMainThread) {
    
    
                liveData.observeForever(observer)

            } else {
    
    
                mainHandler.post {
    
     liveData.observeForever(observer) }
            }
        }

        /**
         * 通过observeForever的,需要手动调用该方法取消订阅
         */
        fun removeObserver(observer: Observer<T>) {
    
    
            if (isMainThread) {
    
    
                removeObserverInternal(observer)
            } else {
    
    
                mainHandler.post {
    
     removeObserverInternal(observer) }
            }
        }
        @MainThread
        private fun removeObserverInternal(observer: Observer<T>) {
    
    
            liveData.removeObserver(observer)
            if (!liveData.hasObservers()) {
    
    
                get().bus.remove(key)
            }
        }

LiveEvent的观察者注册与解绑最终都是在主线程中调用了LiveData的对应方法,并没什么新意。


2)数据更新发布

数据发布提供三种法法post(value)、postDelay(value, delay)、broadcast(value)。该框架支持跨进程通信的实质是通过BroadCastReceiver通信

        /**
         * 发送一个消息,支持前台线程、后台线程发送
         */
        fun post(value: T) {
    
    
            if (isMainThread) {
    
    
                liveData.setValue(value)
            } else {
    
    
                mainHandler.post {
    
     liveData.setValue(value) }
            }
        }

        /**
         * 延迟发送一个消息,支持前台线程、后台线程发送
         *
         * @param delay 延迟毫秒数
         */
        fun postDelay(value: T, delay: Long) {
    
    
            mainHandler.postDelayed({
    
     liveData.setValue(value) }, delay)
        }

        /**
         * 发送一个消息,支持前台线程、后台线程发送
         * 需要跨进程、跨APP发送消息的时候调用该方法
         */
        fun broadcast(value: T) {
    
    
            if (isMainThread) {
    
    
                sendBroad(key, value)
            } else {
    
    
                mainHandler.post {
    
     sendBroad(key, value) }
            }
        }
        
        @SuppressLint("SyntheticAccessor")
        private fun <T> sendBroad(key: String, value: T) {
    
    
            appContext?.let {
    
    
                val intent = Intent(IConst.ACTION)
                intent.putExtra(IConst.KEY, key)
                encode(intent, value)
                it.sendBroadcast(intent)
            }
        }

注意:
通过sendBroad(key, value)方式发布数据时,需要确保参数appContext!=null,所以想要支持广播发送数据,需要调用LiveEventBus.supportBroadcast设置appContext。


LiveEventBus

LiveEvent的管理类,采用单例模式使得其实例在应用中总是唯一。该类中含有一个保存Key与LiveEvent一 一对应关系的MutableMap,通过Key可以快速获得想要操作的LiveEvent。

class LiveEventBus internal constructor() {
    
    
    /**
     * LiveEvent 集合Map
     */
    val bus: MutableMap<String, LiveEvent<*>>
    private var appContext: Context? = null

    /**
     * 单例模式,线程安全类型
     */
    private object SingletonHolder {
    
    
        val DEFAULT_BUS = LiveEventBus()
    }

    companion object {
    
    
        fun get(): LiveEventBus {
    
    
            return SingletonHolder.DEFAULT_BUS
        }
    }

    init {
    
    
        bus = HashMap()
    }

      @Synchronized
    fun <T> with(key: String): LiveEvent<T> {
    
    
        var liveEvent = bus[key]
        return if (liveEvent == null) {
    
    
            liveEvent = LiveEvent<T>(key)
            bus[key] = liveEvent
            liveEvent

        } else {
    
    
            liveEvent as LiveEvent<T>
        }
    }
}

LiveDataReceiver

如果要使用本框架进行跨进程通信,请务必注册该BroadcastReceiver,这样才能接收来自其他进程发送而来的数据。

class LiveDataReceiver : BroadcastReceiver() {
    
    
    fun getIntentFilter(): IntentFilter {
    
    
        val intentFilter = IntentFilter()
        intentFilter.addAction(IConst.ACTION)
        return intentFilter
    }
    override fun onReceive(context: Context, intent: Intent) {
    
    
        if (IConst.ACTION == intent.action) {
    
    
            val key = intent.getStringExtra(IConst.KEY) ?: return
            val valueType = intent.getIntExtra(IConst.VALUE_TYPE, -1)
            if (valueType < 0) {
    
    
                //没有合适的数据
                return
            }
            when (DataType.values()[valueType]) {
    
    
                DataType.STRING -> {
    
    
                    val value = intent.getStringExtra(IConst.VALUE)
                    value?.let {
    
     LiveEventBus.get().with<String>(key).post(it) }
                }
                DataType.INTEGER -> {
    
    
                    val value = intent.getIntExtra(IConst.VALUE, -1)
                    value.let {
    
     LiveEventBus.get().with<Int>(key).post(it) }
                }
                DataType.BOOLEAN -> {
    
    
                    val value = intent.getBooleanExtra(IConst.VALUE, false)
                    value.let {
    
     LiveEventBus.get().with<Boolean>(key).post(it) }
                }
                DataType.LONG -> {
    
    
                    val value = intent.getLongExtra(IConst.VALUE, -1)
                    value.let {
    
     LiveEventBus.get().with<Long>(key).post(it) }
                }
                DataType.FLOAT -> {
    
    
                    val value = intent.getFloatExtra(IConst.VALUE, -1f)
                    value.let {
    
     LiveEventBus.get().with<Float>(key).post(it) }
                }
                DataType.DOUBLE -> {
    
    
                    val value = intent.getDoubleExtra(IConst.VALUE, -1.0)
                    value.let {
    
     LiveEventBus.get().with<Double>(key).post(it) }
                }
                DataType.PARCELABLE -> {
    
    
                    val value: Parcelable? = intent.getParcelableExtra(IConst.VALUE)
                    value?.let {
    
     LiveEventBus.get().with<Parcelable>(key).post(it) }
                }
                DataType.SERIALIZABLE -> {
    
    
                    val value: Serializable? = intent.getSerializableExtra(IConst.VALUE)
                    value?.let {
    
     LiveEventBus.get().with<Serializable>(key).post(it) }
                }
                DataType.UNKNOWN -> throw UnknownError("不支持的数据类型!")
                else -> throw UnknownError("不支持的数据类型!")
            }
        }
    }
}

IConst

该类是一些常量类,一看就懂,不做解释了。

interface IConst {
    
    
    companion object {
    
    
        const val ACTION = "intent.action.ACTION_LIVE_DATA_BUS"
        const val KEY = "key"
        const val VALUE_TYPE = "value_type"
        const val VALUE = "value"
    }
}

enum class DataType {
    
    
    /**
     * 数据枚举类
     */
    STRING, INTEGER, BOOLEAN, LONG, FLOAT, DOUBLE, PARCELABLE, SERIALIZABLE, JSON, UNKNOWN
}

总结

框架结构简单而功能强大,源码https://github.com/l424533553/LiveDataBus.git请自行查阅


相关链接

  1. LiveData原理深入浅出,透过源码看本质
  2. LiveDataBus框架抽丝剥茧后,原来如此简单
  3. Android Room数据库,用过你才知道好

博客书写不易,您的点赞收藏是我前进的动力,千万别忘记点赞、 收藏 ^ _ ^ !

猜你喜欢

转载自blog.csdn.net/luo_boke/article/details/113104570