【问题标题】:How to stop LiveData event being triggered more than Once如何停止多次触发 LiveData 事件
【发布时间】:2019-02-14 10:59:35
【问题描述】:

我在我的应用程序中使用 MutableLiveData 进行基于事件的通信。我有单个活动两个片段架构。

在 ViewModel 的帮助下,我正在使用 Fragment-1 中的 LiveData 事件。但是,当我使用菜单栏将这个 Fragment-1 替换为 Fragment-2 并最终返回到 Fragment-1 时,LiveData 的旧值再次被捕获。

如何避免这个问题?任何帮助/建议都非常感谢! 谢谢。

【问题讨论】:

    标签: android mvvm mutablelivedata


    【解决方案1】:

    您可以使用Event 包装LiveData 值来处理其值的使用,如下文所述: https://medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150

    事件类如下:

    open class Event<out T>(private val content: T) {
    
        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
    }
    

    假设您的 LiveData 值是一个字符串,那么单个事件的 LiveData 将是:

    val navigateToDetails = MutableLiveData&lt;Event&lt;String&gt;&gt;()

    【讨论】:

    • 有效!!谢谢:)
    【解决方案2】:

    无论您在哪里观察 liveData,在 onChanged 方法中通过调用 myLiveDataObject.removeObservers(this); 删除观察者 这将在首次观察到数据后移除观察者。

    【讨论】:

      【解决方案3】:

      接受答案的问题是您只能有一个观察者。 这个article 描述了具有多个观察者的解决方案。

      【讨论】:

        【解决方案4】:

        我遇到了同样的问题并想出了这个库来解决它 https://github.com/ueen/LiveEvent 希望这会有所帮助,享受!

        【讨论】:

          【解决方案5】:

          简单、干净、可重复使用:

          class Event<T>(val payload: T, var broadcasted: Boolean = false)
          
          class MutableEventLiveData<T>: MutableLiveData<Event<T>>() {
              fun postEvent(value: T) {
                  super.postValue(Event(value))
              }
          }
          
          typealias EventLiveData<T> = LiveData<Event<T>>
          
          class EventObserver<T>(private val broadcastCallback: (t: T)->Unit): Observer<Event<T>> {
          
              override fun onChanged(e: Event<T>) {
                  if (!e.broadcasted) {
                      broadcastCallback(e.payload)
                      e.broadcasted = true
                  }
              }
          }
          

          示例用法:

          class YourViewModel : ViewModel() {
              private val _errorEvent = MutableEventLiveData<String>()
              val errorEvent: EventLiveData<String>
                  get() = _errorEvent
          
              fun fireErrorEvent(errorMessage: String) {
                  _errorEvent.postEvent(errorMessage)
              }
              ...
          }
          
          class YourActivity : AppCompatActivity() {
              override fun onCreate(savedInstanceState: Bundle?) {
                  ...
                  //Note!!! EventObserver handles events not Observer
                  viewModel.errorEvent.observe(this, EventObserver { 
                      errorMessage -> showErrorMessage(errorMessage)
                  })
              }
              ...
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-03-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-04-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多