【问题标题】:LiveData confusion in [Android] Plaid App[Android] Plaid App 中的 LiveData 混淆
【发布时间】:2020-07-05 19:46:31
【问题描述】:

我指的是github上的Plaid开源项目Link to Plaid

它是学习 Android 新技术的绝佳资源。

在阅读代码时,我遇到了 LiveData 周围的某种编码风格,我真的不明白。如果有人可以帮助我得到它。 如下:

这段代码有一个ViewModel(vm)

private val _openLink = MutableLiveData<Event<String>>()
val openLink: LiveData<Event<String>>
    get() = _openLink

相当简单?请注意,这里有 2 个变量:openLink_openLinkopenLink 的 getter 正在返回 _openLink LiveData。

在活动中他们观察openLinkLiveData如下:

viewModel.also { vm ->

       vm.openLink.observe(this, EventObserver { openLink(it) })

        ..... // Other stuff
}

现在,另一个 livedata _openLink 被 UI 调用,据称是在单击按钮时,它的定义如下:

fun viewShotRequested() {
    _shotUiModel.value?.let { model -> // ignore this part
        _openLink.value = Event(model.url) // setValue on _openLink
    }
}

所以我的理解是,在setValue()_openLinkEventObserver{openLink(it)} 将被调用。 我的问题是,他们为什么要这样做?

问题:

  1. 为什么不直接观察_openLink上的

  2. 不会有同样的效果吗?我在这里想念什么?

【问题讨论】:

  • 不暴露 Mutable 部分

标签: android android-livedata android-architecture-components plaid


【解决方案1】:

_openLink 是可变的。您必须始终公开不可变且无法由观察者更改的内容,因为这只能由您的 ViewModel 完成,即使公开 _openLink 不会产生任何效果。

这就是为什么您需要公开不可变的openLink

private val _openLink = MutableLiveData<Event<String>>()
val openLink: LiveData<Event<String>> = _openLink

【讨论】:

    【解决方案2】:

    MutableLiveData 属性不应暴露:它是可变的,可以在程序中的任何位置更改。
    这就是为什么LiveData 被公开的原因:它负责更新您的属性,并使用MutableLiveData 作为支持字段。
    这种情况的例外是双向 DataBinding,需要直接访问该值。

    【讨论】:

      【解决方案3】:

      我的问题是,他们为什么要这样做?

      因为 Google 显然喜欢为了编写更多代码而编写更多代码。

      如果你倾向于相信他们,假设的答案是LiveData&lt;Event&lt;T&gt;&gt; is preferred over SingleLiveData because they came up with it later than with LiveData&lt;Event&lt;T&gt;&gt; and is therefore supposedly better

      他们打算使用“可入队的事件总线,它在向至少 1 个观察者发出后会忘记项目”,但 Jetpack 没有提供开箱即用的这种概念,个人 I had to write one of my own

      即便如此,您是否可以写入某些内容与您是否只能读取某些内容而不能自己写入之间是有区别的。在这种情况下,只有 ViewModel 想要能够发出事件,所以 ViewModel 拥有一个 Mutable__ 引用,但向外界公开了一个常规的 LiveData(在我的情况下,EventEmitter 与 @987654329 @)。

      至于_,这是一种 Kotlin 风格的约定,希望有一天会改变,你可以这样做:

      private val _openLink = MutableLiveData<Event<String>>()
      val openLink: LiveData<Event<String>>
          get() = _openLink
      

      但你也可以这样做

      private val openLink = MutableLiveData<Event<String>>()
      fun openLink(): LiveData<Event<String>> = openLink
      

      这样我们就可以在自己的代码中去掉 _ 前缀,但由于某种原因,Kotlin 的作者没有及时提出这个约定。

      【讨论】:

      • 你说得对。我不得不使用Event&lt;T&gt;SingleLiveEvent 来摆脱这种混乱,然后我遇到了这段代码,这让我更加困惑。
      猜你喜欢
      • 2018-02-20
      • 2013-06-21
      • 1970-01-01
      • 2011-04-07
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 2021-06-01
      • 1970-01-01
      相关资源
      最近更新 更多