SingleLiveEvent 发布,如果多次调用,则仅调度最后一个事件(但我需要在我的视图中查看所有事件) [英] SingleLiveEvent post, if called multiple times, then only the last event is dispatched (but I need all events in my view)

查看:84
本文介绍了SingleLiveEvent 发布,如果多次调用,则仅调度最后一个事件(但我需要在我的视图中查看所有事件)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 SingleLiveEvent 来传达我的 ViewModel 和我的活动.类似的东西(伪代码):

I'm using SingleLiveEvent to communicate my ViewModel and my Activity. Something like that (pseudocode):

    class MyActivity: BaseActivity{


fun onCreate(){
//Init viewmodel and so on
 viewModel.commands.observe(this, { command ->
            logger.debug("Command received","------>>>>>>>"+command.javaClass.simpleName)
            processCommand(command)
        })

}

}

我的 ViewModel 类似于:

And my ViewModel is something like:

class MyViewModel(application: Application) : BaseAndroidViewModel(application) {

val command: SingleLiveEvent<CustomCommands> = SingleLiveEvent()

init{

loadOneThing()
command.postValue(CustomCommands.MessageCommand("one thing loaded"))

loadAnotherThing()
command.postValue(CustomCommands.MessageCommand("another thing loaded"))

}
}

我遇到的问题是 Activity 只接收最后一个命令,这是每个设计.SingleLiveEvent 是 LiveData 的 Child 类,文档中对 postValue 方法做了如下说明:

The problem that I'm having, is that the Activity is receiving only the last command, and that is per design. SingleLiveEvent is a Child class from LiveData, and the documentation says the following for the method postValue:

  • * 如果在主线程执行发布任务之前多次调用此方法,则仅* 将发送最后一个值.

有趣的是,如果我在发布命令的行上设置断点,模拟器/设备/主线程有足够的时间来处理第一个命令,第二个命令也会被发送.但是在没有断点的情况下执行应用程序时,如果视图模型在命令之间执行的任务完成得非常快(没有休息请求或类似的事情,但有一些计算),主线程没有足够的时间来完成第一个命令,并且第二个命令被忽略.

Interestingly, if I set a breakpoint on the line that posts the commands, the emulator/device/main thread has time enough to process the first command, and the second command is sent too. But when executing the app without breakpoints, if the tasks that the viewmodel does between commands are done very fast (no rest requests or things like that, but some calculations), the main thread does not have time enough to finish the first command, and the second command is ignored.

但我真的需要 View 来接收 ViewModel 发送的所有事件/命令.

But I really need the View to receive all events/commands that the ViewModel sends.

我认为 SingleLiveEvent 不是该用例的正确工具,LiveData 也不是,因为在设备旋转时会重新发送已经消耗的事件等问题.

I suppose the SingleLiveEvent is not the right tool for that use case, nor is LiveData, because of the problem of already consumed events being resent when the device is rotated and so on.

有人知道更好的方法吗?

Somebody knows a better approach to do this?

提前致谢!

推荐答案

您是否尝试过使用 EventObserver?

have you tried using EventObserver?

/**
 * Used as a wrapper for data that is exposed via a LiveData that represents an event.
 */
open class Event<out T>(private val content: T) {

    @Suppress("MemberVisibilityCanBePrivate")
    var hasBeenHandled = false
        private set // Allow external read but not write

    /**
     * Returns the content and prevents its use again.
     */
    fun getContentIfNotHandled(): T? {
        return if (hasBeenHandled) {
            null
        } else {
            hasBeenHandled = true
            content
        }
    }

    /**
     * Returns the content, even if it's already been handled.
     */
    fun peekContent(): T = content
}

/**
 * An [Observer] for [Event]s, simplifying the pattern of checking if the [Event]'s content has
 * already been handled.
 *
 * [onEventUnhandledContent] is *only* called if the [Event]'s contents has not been handled.

*/

class EventObserver<T>(private val onEventUnhandledContent: (T) -> Unit) : Observer<Event<T>> {
    override fun onChanged(event: Event<T>?) {
        event?.getContentIfNotHandled()?.let {
            onEventUnhandledContent(it)
        }
    }
}

将其与实时数据结合使用

Use it with live data

val someEvent: MutableLiveData<Event<Unit>>= MutableLiveData()

当你需要参加一些活动时

when you need to some event

fun someEventOccured(){
   someEvent.value = Event(Unit)
}

碎片文件,观察事件

viewModel.someEvent.observe(this, EventObserver {
    //somecode
})

这篇关于SingleLiveEvent 发布,如果多次调用,则仅调度最后一个事件(但我需要在我的视图中查看所有事件)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆