Android LiveData阻止在观察时收到最后一个值 [英] Android LiveData prevent receive the last value on observe

查看:548
本文介绍了Android LiveData阻止在观察时收到最后一个值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以防止LiveData在开始观察时接收到最后一个值? 我正在考虑使用LiveData作为事件.

Is it possible to prevent LiveData receive the last value when start observing? I am considering to use LiveData as events.

例如类似于EventBus的显示消息,导航事件或对话框触发器之类的事件.

For example events like show message, a navigation event or a dialog trigger, similar to EventBus.

ViewModel和fragment之间的通信有关的问题,Google给了我们LiveData用数据更新视图,但是这种类型的通信不适用于我们仅需要通过单个事件更新一次视图的情况,因此我们无法在ViewModel中保存视图的引用并调用一些方法,因为这会导致内存泄漏.

The problem related to communication between ViewModel and fragment, Google gave us LiveData to update the view with data, but this type of communication not suitable when we need update the view only once with single event, also we cannot hold view's reference in ViewModel and call some methods because it will create memory leak.

我发现了类似的内容

I found something similar SingleLiveEvent - but it work only for 1 observer and not for multiple observers.

---更新----

@EpicPandaForce说"没有理由将LiveData用作不是它的东西",问题的意图可能是

As @EpicPandaForce said "There is no reason to use LiveData as something that it is not", probably the intent of the question was Communication between view and ViewModel in MVVM with LiveData

推荐答案

没有理由将LiveData用作不是.如果您需要单独的行为(某种东西不会保留以前的值),那么您应该使用一个不能保留以前的值的组件-而不是乱砍它(记住"它已经发出并忘记了)发射等等)

There is no reason to use LiveData as something that it is not. If you need a separate behavior (something that doesn't retain the previous value), then you should use a component that doesn't retain the previous value -- instead of hacking around it ("remembering" that it had emitted and then forgetting to emit, etc.)

您可以添加event-emitter库:

implementation 'com.github.Zhuinden:event-emitter:1.1.0'

来自Jitpack:maven { url "https://jitpack.io" }

from Jitpack: maven { url "https://jitpack.io" }

那你就可以做

// read
private var subscription: EventSource.NotificationToken? = null

fun observe() {
    subscription = events.startListening { event ->
        showToast(event)
    }
}

fun unsubscribe() {
    subscription?.stopListening()
    subscription = null
}

但是如果您需要像这样使用它:

But if you need to use it like this:

    controllerEvents.observe(viewLifecycleOwner) { event: WordController.Events ->
        when (event) {
            is WordController.Events.NewWordAdded -> showToast("Added ${event.word}")
        }.safe()
    }

然后您就可以使用

import android.arch.lifecycle.Lifecycle
import android.arch.lifecycle.LifecycleObserver
import android.arch.lifecycle.LifecycleOwner
import android.arch.lifecycle.OnLifecycleEvent
import com.zhuinden.eventemitter.EventSource

private class LiveEvent<T> constructor(
    private val eventSource: EventSource<T>,
    private val lifecycleOwner: LifecycleOwner,
    private val observer: EventSource.EventObserver<T>
) : LifecycleObserver {
    init {
        if (lifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.INITIALIZED)) {
            lifecycleOwner.lifecycle.addObserver(this)
        }
    }

    private var isActive: Boolean = false
    private var notificationToken: EventSource.NotificationToken? = null

    private fun shouldBeActive(): Boolean {
        return lifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)
    }

    private fun disposeObserver() {
        lifecycleOwner.lifecycle.removeObserver(this)
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        if (lifecycleOwner.lifecycle.currentState == Lifecycle.State.DESTROYED) {
            stopListening()
            disposeObserver()
            return
        }
        checkIfActiveStateChanged(shouldBeActive())
    }

    private fun checkIfActiveStateChanged(newActive: Boolean) {
        if (newActive == isActive) {
            return
        }
        val wasActive = isActive
        isActive = newActive
        val isActive = isActive

        if (!wasActive && isActive) {
            stopListening()
            notificationToken = eventSource.startListening(observer)
        }

        if (wasActive && !isActive) {
            stopListening()
        }
    }

    private fun stopListening() {
        notificationToken?.stopListening()
        notificationToken = null
    }
}

fun <T> EventSource<T>.observe(lifecycleOwner: LifecycleOwner, eventObserver: (T) -> Unit) {
    LiveEvent(this, lifecycleOwner, EventSource.EventObserver<T> { event -> eventObserver.invoke(event) })
}

这篇关于Android LiveData阻止在观察时收到最后一个值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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