关于kotlin中的flow(三)-使用flow来实现eventbus

13,208 阅读1分钟

上一章关于kotlin中的flow(二)

本章主要是使用flow来实现一个eventbus。 首先需要确定使用哪一种flow,eventbus作为事件总线,根据上一章对StateFlow和SharedFlow侧重的区别,可以明确应该使用MutableSharedFlow。 废话不多,直接上代码:

object FlowEventBus {
    private val bus: HashMap<String, MutableSharedFlow<out Any>> = hashMapOf()

    private fun <T : Any> with(key: String): MutableSharedFlow<T> {
        if (!bus.containsKey(key)) {
            val flow = MutableSharedFlow<T>()
            bus[key] = flow
        }
        return bus[key] as MutableSharedFlow<T>
    }

    /**
     * 对外只暴露SharedFlow
     * @param action String
     * @return SharedFlow<T>
     */
    fun <T> getFlow(action: String): SharedFlow<T> {
        return with(action)
    }


    /**
     * 挂起函数
     * @param action String
     * @param data T
     */
    suspend fun <T : Any> post(action: String, data: T) {
        with<T>(action).emit(data)
    }

    /**
     * 详见tryEmit和emit的区别
     * @param action String
     * @param data T
     * @return Boolean
     */
    fun <T : Any> tryPost(action: String, data: T): Boolean {
        return with<T>(action).tryEmit(data)
    }

    /**
     * sharedFlow会长久持有,所以要加声明周期限定,不然会出现内存溢出
     * @param lifecycle Lifecycle
     * @param action String
     * @param block Function1<T, Unit>
     */
    suspend fun <T : Any> subscribe(lifecycle: Lifecycle, action: String, block: (T) -> Unit) {
        lifecycle.repeatOnLifecycle(Lifecycle.State.CREATED) {
            with<T>(action).collect {
                block(it)
            }
        }
    }

    /**
     * 注意,使用这个方法需要将协程在合适的时候取消,否则会导致内存溢出
     * @param action String
     * @param block Function1<T, Unit>
     */
    suspend fun <T : Any> subscribe(action: String, block: (T) -> Unit) {
        with<T>(action).collect {
            block(it)
        }
    }

}

这样一个最基本的eventbus就已经完成了。

订阅数据:

val liveData = FlowEventBus.getFlow<String>("action.onMessage").asLiveData()
fun subscribeEvent() {
    lifecycleScope.launch {
        FlowEventBus.subscribe<String>(lifecycle, "action.onMessage") {
            Log.d(TAG, "testShardFlow: getMsg $it")
        }
    }
    liveData.observe(this) {
        mDataBinding.tvEventBus.text = it
    }
}

发送数据

fun testSharedFlow() {
    viewModelScope.launch {
        FlowEventBus.post("action.onMessage", "send msg")
    }
}

一个基础的eventBus就完成了,剩下的就是通过反射,获取注解,然后绑定注解中的action订阅数据,就实现了类似eventBus中的使用方式