Android 按钮单击事件的 Kotlin 协程流程示例?

Zou*_* Ng 9 android kotlin anko kotlin-coroutines

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

我迁移了下面的代码:

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

// Anko
button {
    onClick {
        btnProduceChannel.send(Unit)
    }
}
Run Code Online (Sandbox Code Playgroud)

到:

lateinit var btnFlow: Flow<Unit>
    private set

button {
    btnFlow = flow { 
       onClick { 
            emit(Unit) 
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

我必须像var现在一样标记流属性,这不像以前那么优雅。这种方式对吗?我可以初始化一个的RxSubjectFlow定义属性是什么时候?


编辑:

我带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
Run Code Online (Sandbox Code Playgroud)

这似乎比lateinit var一个更好,但有什么办法可以Channel完全摆脱?(虽然Flow本身喜欢callbackFlowchannelFlow正在使用频道)

Sta*_*lov 18

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

fun View.clicks(): Flow<Unit> = callbackFlow {
    setOnClickListener {
        offer(Unit)
    }
    awaitClose { setOnClickListener(null) }
}
Run Code Online (Sandbox Code Playgroud)

一个可能的用法示例是:

button.clicks()
   .onEach { /*React on a click event*/ }
   .launchIn(lifecycleScope)
Run Code Online (Sandbox Code Playgroud)