当ViewModel通过LiveData公开UiModel时,如何对UiModel中的更改做出反应?

问题描述 投票:0回答:1

[我观看了Florina Muntenescu在KontlinConf 2018上的精彩演讲,她谈到了他们如何重塑其应用程序架构。

讨论的一部分是他们如何通过ViewModel中的LiveData公开UiModel(not 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本身的属性变化做出反应。 每次文本更改时如何执行功能?

[当在ViewModel内的单独LiveData属性中包含text时,我可以像这样使用MediatorLiveData:

myMediatorLiveData.addSource(text){
   // do something when text changed
}

但是当使用上面的方法时,UiModel不会更改,而是会更改其值。所以这在这里不起作用:

myMediatorLiveData.addSource(uiModel){
   // do something when text inside uiModel changed
}

所以我的问题是如何用这种方法对ViewModel中的UiModel内部的更改做出反应?

感谢您的建议,克里斯

android android-livedata android-architecture-components android-viewmodel
1个回答
0
投票

我想总结关于上述主题的研究。

正如@CommonsWars在注释above中所说,您可以将UiModel中的字段实现为ObservableFields。但是经过一些实践之后,我目前更喜欢ObservableField中描述的方法。

这导致我找到以下代码:

ViewModel:

here

UiModel

class MyViewModel constructor(...) : ViewModel() {
   val uiModel = liveData{
       val UiModel uiModel = UiModel() // get the model from where ever you want
       emit(uiModel)
   }

   fun doSomething(){
      uiModel.value!!.username = "abc"
   }
}

布局

class UiModel : BaseObservable() {

   @get:Bindable // puts '@Bindable' on the getter
   var text = ""
      set(value) {
         field = value
         notifyPropertyChanged(BR.text) // trigger binding
      }

   val isValid: Boolean
   @Bindable("text") get() { // declare 'text' as a dependency
      return !text.isBlank()
   }
}

我之所以选择这种方法,是因为我们从ViewModel中更改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}" /> <Button android:id="@+id/sent_btn" android:enabled="@{viewModel.uiModel.isValid}" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>

username

当您通过ObservableFields实现它时,必须通过以下方式设置/获取fun doSomething(){ uiModel.value!!.username = "abc" } fun doSomething(){ uiModel.value!!.username }

username

您可以选择最适合您需求的方法!希望这对某人有帮助。

克里斯

© www.soinside.com 2019 - 2024. All rights reserved.