SharedFlowBus:30行代码实现消息总线你确定不看吗
前言
最近看到很多关于livedata和flow的文章,大家都在学那我肯定不能落后。便去学习一番,偶得SharedFlowBus
(卷死你们)。
那么正式开始前我们先大概了解下 StateFlow
和 SharedFlow
StateFlow
StateFlow
是一个状态容器式可观察数据流,可以向其收集器发出当前状态更新和新状态更新。还可通过其value属性读取当前状态值。
在 Android 中,StateFlow
非常适合需要让可变状态保持可观察的类。
与使用 flow
构建器构建的冷数据流不同,StateFlow
是热数据流:从此类数据流收集数据不会触发任何提供方代码。StateFlow
始终处于活跃状态并存于内存中,而且只有在垃圾回收根中未涉及对它的其他引用时,它才符合垃圾回收条件。
当新使用方开始从数据流中收集数据时,它将接收信息流中的最近一个状态及任何后续状态。您可在 LiveData
等其他可观察类中找到此操作行为。
SharedFlow
SharedFlow
是 StateFlow
的可配置性极高的泛化数据流。您可以使用 SharedFlow
将 tick 信息发送到应用的其余部分,以便让所有内容定期同时刷新。除了获取最新资讯之外,您可能还想要使用用户最喜欢的主题集刷新用户信息部分。
class MainViewModel : ViewModel() {
private val _sharedFlow = MutableSharedFlow<Int>(0, 1, BufferOverflow.DROP_OLDEST)
val sharedFlow: SharedFlow<Int> = _sharedFlow
init {
viewModelScope.launch {
for (i in 0..10) {
sharedFlow.tryEmit(i)
}
}
}
}
class MainFragment : Fragment() {
private val viewModel: MainViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
CoroutineScope(Dispatchers.Main).launch {
viewModel.sharedFlow.collect {
println(it)
}
}
}
}
您可通过以下方式自定义 SharedFlow
行为:
- 通过
replay
,您可以针对新订阅者重新发送多个之前已发出的值。 - 通过
onBufferOverflow
,您可以指定相关政策来处理缓冲区中已存满要发送的数据项的情况。默认值为BufferOverflow.SUSPEND
,这会使调用方挂起。其他选项包括DROP_LATEST
或DROP_OLDEST
。
MutableSharedFlow
还具有 subscriptionCount
属性,其中包含处于活跃状态的收集器的数量,以便您相应地优化业务逻辑。MutableSharedFlow
还包含一个 resetReplayCache
函数,供您在不想重放已向数据流发送的最新信息的情况下使用。
没错,以上信息摘自 Android Developers ,我真是太能水了,干脆改行写小说得了哈哈哈。
SharedFlowBus的使用
// 发送消息
SharedFlowBus.with(objectKey: Class<T>).tryEmit(value: T)
// 发送粘性消息
SharedFlowBus.withSticky(objectKey: Class<T>).tryEmit(value: T)
// 订阅消息
SharedFlowBus.on(objectKey: Class<T>).observe(owner){ it ->
println(it)
}
// 订阅粘性消息
SharedFlowBus.onSticky(objectKey: Class<T>).observe(owner){ it ->
println(it)
}
通过上面的使用方法可以看出 SharedFlowBus
的优点
- 使用者不用显示调用反注册方法。
- 感知生命周期,防止内存泄漏。
- 实时数据刷新。
SharedFlowBus的实现
object SharedFlowBus {
private var events = ConcurrentHashMap<Any, MutableSharedFlow<Any>>()
private var stickyEvents = ConcurrentHashMap<Any, MutableSharedFlow<Any>>()
fun <T> with(objectKey: Class<T>): MutableSharedFlow<T> {
if (!events.containsKey(objectKey)) {
events[objectKey] = MutableSharedFlow(0, 1, BufferOverflow.DROP_OLDEST)
}
return events[objectKey] as MutableSharedFlow<T>
}
fun <T> withSticky(objectKey: Class<T>): MutableSharedFlow<T> {
if (!stickyEvents.containsKey(objectKey)) {
stickyEvents[objectKey] = MutableSharedFlow(1, 1, BufferOverflow.DROP_OLDEST)
}
return stickyEvents[objectKey] as MutableSharedFlow<T>
}
fun <T> on(objectKey: Class<T>): LiveData<T> {
return with(objectKey).asLiveData()
}
fun <T> onSticky(objectKey: Class<T>): LiveData<T> {
return withSticky(objectKey).asLiveData()
}
}
源码说明
以上就是 SharedFlowBus
的源码,可以直接拷贝到项目中使用。