【发布时间】:2020-02-23 12:30:34
【问题描述】:
我在 KontlinConf 2018 上观看了 Florina Muntenescu 的精彩演讲,她谈到了他们如何重塑应用架构。
谈话的一部分是他们如何通过来自 ViewModel 的 LiveData 公开 UiModel(不是 ViewModel)。 (watch here)
她做了一个类似这样的例子:
class MyViewModel constructor(...) : ViewModel() {
private val _uiModel = MutableLiveData<UiModel>()
val uiModel: LiveData<UiModel>
get() = _uiModel
}
上面 ViewModel 的视图声明可以是:
<layout>
<data>
<variable
name="viewModel"
type="com.demo.ui.MyViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout>
<EditText
android:id="@+id/text"
android:text="@={viewModel.uiModel.text}" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
她没有谈到(或者我错过了)他们如何对 UiModel 本身的属性变化做出反应。 如何在每次文本更改时执行函数?
当 text 在 ViewModel 中的单独 LiveData 属性中时,我可以使用 MediatorLiveData,例如:
myMediatorLiveData.addSource(text){
// do something when text changed
}
但是当使用上面的方法时,UiModel 并没有改变,而是它的值被改变了。所以这在这里不起作用:
myMediatorLiveData.addSource(uiModel){
// do something when text inside uiModel changed
}
所以我的问题是如何使用这种方法对 ViewModel 中的 UiModel 内的变化做出反应?
感谢您的建议, 克里斯
【问题讨论】:
-
“但是当使用上面的方法时,UiModel 并没有改变,而是它的值被改变了”——这段代码中没有任何暗示。如果有的话,我希望情况并非如此。恕我直言,
UiModel应该是带有val属性的data class,因此它是不可变的,并且当text需要更改时,应该通过LiveData发布一个新的UiModel实例。 -
感谢您的回复。当您查看声明的视图时,您会注意到“android:text="@={viewModel.uiModel.text" 这意味着 UiModel 中的“文本”发生了变化。在这种情况下,我无法对变化做出反应,也无法't 整体交换 UiModel。对吗?!
-
没错,他们使用的是双向绑定。我注意到了这一点。就个人而言,我不喜欢双向数据绑定,所以我没有考虑这一点。在这种情况下,
text需要单独观察,例如使用the data bindingObservableFieldclass。如果是这样,您可以自己观察text。
标签: android android-livedata android-architecture-components android-viewmodel