Android Architecture Components 系列目录
博客创建时间:2021.01.23
博客更新时间:2020.01.27
以Android studio 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)方式注册 LiveDataBus.observe(LiveDataBus.LIVE_EVENT_BUS_COMMON_LIVE_STRING, this, observer); //1.注册监听 observeForever(observer)方式注册 LiveDataBus.observeForever("LIVE_EVENT_BUS_COMMON_LIVE_STRING", observer);
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的调用在主线程中。
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请自行查阅