Android 当UiModel';ViewModel通过LiveData公开了哪些内容?

Android 当UiModel';ViewModel通过LiveData公开了哪些内容?,android,android-livedata,android-architecture-components,android-viewmodel,Android,Android Livedata,Android Architecture Components,Android Viewmodel,我观看了Florina Muntenescu在2018年KontlinConf上的精彩演讲,她谈到了他们如何重塑应用程序架构 会谈的一部分是他们如何通过ViewModel中的LiveData公开UiModel(非ViewModel)。() 她举了一个类似的例子: class MyViewModel constructor(...) : ViewModel() { private val _uiModel = MutableLiveData<UiModel>() va

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

会谈的一部分是他们如何通过ViewModel中的LiveData公开UiModel(ViewModel)。()

她举了一个类似的例子:

class MyViewModel constructor(...) : ViewModel() {

    private val _uiModel = MutableLiveData<UiModel>()
    val uiModel: LiveData<UiModel>
        get() = _uiModel
}

但是当使用上面的方法时,UiModel并没有改变,而是改变了它的值。所以这不起作用:

myMediatorLiveData.addSource(uiModel){
   // do something when text inside uiModel changed
}
因此,我的问题是我如何使用这种方法对ViewModel中UiModel内部的更改作出反应?

谢谢你的建议,
克里斯

我想总结一下我对上述主题的研究

正如@CommonsWars在评论中所说的,您可以将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"
   }
}
UiModel

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()
   }
}
布局

<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>
当您通过ObservableFields实现它时,您必须通过以下方式设置/获取
用户名

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

fun doSomething(){
   uiModel.value!!.username.get()
}
您可以选择最适合您需要的方法! 希望这对别人有帮助


Chris

“但是当使用上面的方法时,UiModel并没有改变,而是改变了它的值”——这段代码中没有任何东西暗示这一点。如果有什么不同的话,我希望情况并非如此。总之,
UiModel
应该是一个具有
val
属性的
data类,因此它是不可变的,当
text
需要更改时,应该通过
LiveData
发布一个新的
UiModel
实例。谢谢您的回复。查看声明的视图时,您会注意到“android:text=“@={viewModel.uiModel.text”,这意味着“text”的更改"在UiModel中。在这种情况下,我无法对更改做出反应,也无法整体交换UiModel。对吧?!没错,他们使用的是双向绑定。我已经注意到了。就个人而言,我不喜欢双向数据绑定,所以我没有考虑到这一点。在这种情况下,
文本
需要单独观察,例如使用。如果是这样,您可以然后你自己观察
text
<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>
fun doSomething(){
   uiModel.value!!.username = "abc"
}

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

fun doSomething(){
   uiModel.value!!.username.get()
}