Flow:30行代码实现自己的消息总线,你确定不学吗

3,647 阅读3分钟

前言

最近看到很多关于livedata和flow的文章,大家都在学那我肯定不能落后。便去学习一番,偶得SharedFlowBus(卷死你们)。

那么正式开始前我们先大概了解下 StateFlowSharedFlow

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 的源码,可以直接拷贝到项目中使用。

最后推荐下自己的 fragmject ,真正的入门级的项目,通过对KotlinJetpack全家桶的系统运用,实现的一个功能完备符合主流市场标准App。 一个代码够简单,内容够全面,知识够详细,能让你快速上手的项目,对理解其他项目设计思想和封装技巧也很有帮助。

Thanks

以上就是本篇文章的全部内容,如有问题欢迎指出,我们一起进步。 如果喜欢的话希望点个赞吧,您的鼓励是我前进的动力。 谢谢~~