簡體   English   中英

導航組件 - Livedata 生命周期問題

[英]Navigation Component - Problem with Livedata lifecycle

我從導航組件開始,我在使用實時數據觀察器時遇到了一些問題。

例如:我有這個 livedata,它管理來自服務器的身份驗證響應。

viewModel.authenticate.observe(this, Observer {
        manageAuthResponse(it)
        })

一切正常,然后我轉到片段 B。但是當我在片段 B 中時,我嘗試返回片段 A(包含該實時數據), Observer再次觸發,並顯示先前的結果 (SUCCESS)。

我怎樣才能防止這種情況?

當我回去時,我想刷新這個結果並防止 livedata 觀察者被解雇。

將您的 LiveData 對象包裝在這樣的ConsumableValue

class ConsumableValue<T>(private val data: T) {

    private var consumed = false

    fun consume(block: ConsumableValue<T>.(T) -> Unit) {
        if (!consumed) {
            consumed = true
            block(data)
        }
    }
}

然后在視圖模型中

val authenticate = MutableLiveData<Consumable<AuthenticationObject>>()

在你的片段中

viewModel.authenticate.observe(this, Observer { consumable ->
        consumable.consume {
            manageAuthResponse(it)
        }
    })

像這樣包裝 LiveDate

open class LiveEvent<T> : MediatorLiveData<T>() {

  private val observers = ArraySet<ObserverWrapper<in T>>()

  @MainThread
  override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
    val wrapper = ObserverWrapper(observer)
    observers.add(wrapper)
    super.observe(owner, wrapper)
  }

  @MainThread
  override fun observeForever(observer: Observer<in T>) {
    val wrapper = ObserverWrapper(observer)
    observers.add(wrapper)
    super.observeForever(wrapper)
  }

  @MainThread
  override fun removeObserver(observer: Observer<in T>) {
    if (observers.remove(observer)) {
      super.removeObserver(observer)
      return
    }
    val iterator = observers.iterator()
    while (iterator.hasNext()) {
      val wrapper = iterator.next()
      if (wrapper.observer == observer) {
        iterator.remove()
        super.removeObserver(wrapper)
        break
      }
    }
  }

  @MainThread
  override fun setValue(t: T?) {
    observers.forEach { it.newValue() }
    super.setValue(t)
  }

  private class ObserverWrapper<T>(val observer: Observer<T>) : Observer<T> {

    private var pending = false

    override fun onChanged(t: T?) {
      if (pending) {
        pending = false
        observer.onChanged(t)
      }
    }

    fun newValue() {
      pending = true
    }
  }
}

然后在 ViewModel

val viewModel = LiveEvent<Resource<String>>()

這個解決方案對我有用

你可以查看這個github中的代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM