【问题标题】:Kotlin coroutine flow example for Android button click event?Android按钮点击事件的Kotlin协程流程示例?
【发布时间】:2020-01-13 21:26:57
【问题描述】:

我曾经使用Channel 将点击事件从Anko View 类发送到Activity 类,但是越来越多的Channel 函数被标记为已弃用。所以我想开始使用Flow apis。

我迁移了以下代码:

private val btnProduceChannel = Channel<Unit>()
val btnChannel : ReceiveChannel<Unit> = btnProduceChannel 

// Anko
button {
    onClick {
        btnProduceChannel.send(Unit)
    }
}

到:

lateinit var btnFlow: Flow<Unit>
    private set

button {
    btnFlow = flow { 
       onClick { 
            emit(Unit) 
       }
    }
}

我现在必须将流属性标记为var,这不像以前那么优雅了。这种方式对吗?我可以在定义属性时像 Flow 一样初始化 Rx Subject 吗?


编辑:

我把Channel带回来,然后用consumeAsFlow()

private val btnChannel = Channel<Unit>()

// This can be collected only once
val btnFlow = btnChannel.consumeAsFlow()

// Or add get() to make property can be collected multiple times
// But the "get()" can be easily forgotten and I don't know the performance of create flow every access
val btnFlow get() = btnChannel.consumeAsFlow()


// Send event with btnChannel

这似乎比lateinit var 更好,但是有什么方法可以完全摆脱Channel? (虽然Flow 本身像callbackFlowchannelFlow 都在使用频道)

【问题讨论】:

    标签: android kotlin kotlin-coroutines anko


    【解决方案1】:

    虽然我的项目中没有使用 Anko,但我已经编写了这个函数来与常规按钮引用一起使用,看看它是否对你有帮助:

    fun View.clicks(): Flow<Unit> = callbackFlow {
        setOnClickListener {
            offer(Unit)
        }
        awaitClose { setOnClickListener(null) }
    }
    

    一个可能的用法示例是:

    button.clicks()
       .onEach { /*React on a click event*/ }
       .launchIn(lifecycleScope)
    

    更新

    正如@Micer 在原始答案的 cmets 中提到的那样,Channel#offer 方法已被弃用,取而代之的是 Channel#trySend 方法。

    更新版本:

    fun View.clicks() = callbackFlow<Unit> {
        setOnClickListener {
            trySend(Unit)
        }
        awaitClose { setOnClickListener(null)}
    }
    

    【讨论】:

    • 感谢分享这个有用的 kotlin 扩展!这取代了我的旧RxView.clicks(view) :)
    • lifecycleScope.launch.launchIn(lifecycleScope)有什么区别?
    • 伙计们出于某种原因它在 AppcompatButton 上不起作用
    • @IgorGanapolsky 除了在某些情况下更方便之外,它是一个终端语句,几乎总是需要onEach() 之前
    • offer 已弃用,应替换为 trySend
    猜你喜欢
    • 2011-12-30
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2021-01-04
    相关资源
    最近更新 更多