将java监听器转换为kotlin流



我在Android上开发,在我的源代码中有很多基于回调的监听器。我想把其中的一部分转化为kotlin流。我读了很多关于callbackFlow的文章,但我认为这对我来说不是一个正确的选择

在我的情况下,有这样的东西:

interface ActionListener{
public void actionStarted(actionId:Int)
public void actionProgress(actionId:Int, elementCreated:ExampleElement)
public void actionEnd(actionId:Int)
}
class MainProductor{
ActionListener actionListener;

MainProductor(ActionListener actionListener){
this.actionListener = actionListener
}

void start(){
//start some heavy works that start to call actionListener
}
}

用例:当我调用时,启动一些具有特定id的操作,并开始创建一些ExampleElement在UI中,我必须显示id为a和id为B的操作产生的ExampleElement的列表。

在UI中,我必须显示两个动作中的一个动作开始时的进度,直到创建了两个动作ID产生的所有元素,(这部分太棘手了(

如何继续使用这个ActionListener并使其适应新的kotlin流?有可能的办法吗?

使用callbackFlow的要点是在启动/取消时自动注册和注销侦听器。处理多个回调方法的一个可能的解决方案是创建相应的事件类并发出它们。

sealed interface ActionListenerEvent {
class Started(val actionId: Int) : ActionListenerEvent
class ProgressChanged(val actionId: Int, val progress: Float, val elementCreated: ExampleElement) : ActionListenerEvent
class Finished(val actionId: Int) : ActionListenerEvent
}

fun actionEvents() = callbackFlow {
val listener = object : ActionListener {
override fun actionStarted(actionId: Int) {
trySend(ActionListenerEvent.Started(actionId))
}
override fun actionProgress(actionId: Int, progress: Float, elementCreated: ExampleElement) {
trySend(ActionListenerEvent.ProgressChanged(actionId, progress, elementCreated))
}
override fun actionEnd(actionId: Int) {
trySend(ActionListenerEvent.Finished(actionId))
}
}
registerListener(listener)
awaitClose {
unregisterListener(listener)
}
}

如果您想要一个对侦听器的注册/未注册时间有更多控制的解决方案,还可以使用MutableSharedFlow来公开事件。

class MainProductor{
val events = MutableSharedFlow<ActionListenerEvent>() // may need to configure replay and buffer depending on your specific use case
private val listener  = object : ActionListener {
override fun actionStarted(actionId: Int) {
events.tryEmit(ActionListenerEvent.Started(actionId))
}
override fun actionProgress(actionId: Int, progress: Float, elementCreated: ExampleElement) {
events.tryEmit(ActionListenerEvent.ProgressChanged(actionId, progress, elementCreated))
}
override fun actionEnd(actionId: Int) {
events.tryEmit(ActionListenerEvent.Finished(actionId))
}
}

fun start(){
registerListener(this.listener)
}

fun stop(){
unregisterListener(this.listener)
}
}

编辑:示例用法

虽然我不完全确定预期的行为,特别是如何处理elementCreated: ExampleElement部分,但我认为您希望显示当前正在运行的操作及其各自进度的列表。将事件聚合到这样的列表中可能看起来像这样:

data class RunningAction(val id: Int, val progress: Float)// TODO integrate "elementCreated"
fun collectEvents() = flow {
val runningActions = mutableMapOf<Int, RunningAction>()
actionEvents().collect { event ->
when (event) {
is ActionListenerEvent.Started -> {
runningActions[event.actionId] = RunningAction(id = event.actionId, progress = 0f)
}
is ActionListenerEvent.ProgressChanged -> {
val action = runningActions[event.actionId]
if(action != null){
runningActions[event.actionId] = action.copy(progress = event.progress) // TODO integrate "elementCreated"
}
}
is ActionListenerEvent.Finished -> {
runningActions.remove(event.actionId)
}
}
emit(runningActions.values)
}
}

最新更新