如何从模型业务逻辑更新UI?

问题描述

用例:一个简单的计费应用。

当数量价格发生变化时,总数应发生变化。

我正在使用DataBinding,如何通知UI total已更改?

型号:

class Detail(){
    private var _quantity = BigDecimal.ZERO
    private var _price = BigDecimal.ZERO
    private var _total = BigDecimal.ZERO

    var quantity : BigDecimal
    get() = _quantity
    set(value){
        _quantity = value
        compute()
    }

    //same boilerplate for price

   private fun compute(){
       total = price.mutiply(quantity)
   }
}

ViewModel

    var instance = Detail()

    fun addQuantity(){
         instance.quantity.add(1)
    }
    
    fun addPrice(){
         instance.price.add(1)
    }

查看

    <button onClick="@{() -> viewModel.addQuantity()}"
    <button onClick="@{() -> viewModel.addPrice()}"
    <textview text="@{viewModel.instance.total}"/>

我的第一个想法是制作一个LiveData,但是我找不到任何文档说明在模型中创建LiveData属性是一个好主意。据我了解,它们应该专门位于ViewModel中。

我还是尝试了一下,但是发现了另一个问题。我只能使其响应1个属性,但需要响应2个属性(数量和价格)

var quantity = MutableLiveData<BigDecimal>()
var price = MutableLiveData<BigDecimal>()

var total = Transformations.map(quantity){ ... } 
var total = Transformation.map(price){ ...} // Duplicate property!

什么是正确的方法?

在.net世界中,您只需调用NotifyPropetyChanged()即可,UI会知道。我在Android中找不到类似的逻辑。

解决方法

我认为您可以按照Google的代码实验室中的指南进行数据绑定。

https://codelabs.developers.google.com/codelabs/android-databinding

简而言之,您可以使用LiveData来更新视图。这样,您的视图模型应该像这样

private val _quantity = MutableLiveData("100")
val quantity = _quantity

xml布局

<data>
   <variable
      name="viewmodel"
      type="myviewmodel.SimpleViewModel"/>
</data>

<TextView
   android:id="@+id/quantity_text"
   android:text="@{viewmodel.quantity}"
/>

将此添加到活动级别

binding.lifecycleOwner = this

只需按照链接示例获取更多详细信息

,

在viewModel中将实例作为LiveData

val instance = MutableLiveData<Detail>()

fun addQuantity(){
     instance.value.quantity.add(1)
}

fun addPrice(){
     instance.value.price.add(1)
}

在“片段/活动”中,请确保添加此行以进行绑定

binding.lifecycleOwner = viewLifecycleOwner

确保您拥有该库以使用viewLifecycleOwner

 implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0'
,

是的,您的直觉是正确的。 LiveDataViewModel的专有内容,但不仅限于ViewModel。 MVVM体系结构方法建议在LiveData s中加入ViewModel

无论如何,我们假设您有两个实时数据,分别为quantityprice。现在,如果total依赖于这两个实时数据,则可以将其设为MediatorLiveData,然后观察这两个属性以确保在(已更改)都可用时,结果始终会得到反映。

下面的示例是您的操作方式:

var quantity = MutableLiveData<BigDecimal>()
var price = MutableLiveData<BigDecimal>()

val total = MediatorLiveData<BigDecimal>().apply {
    var updatedQty = 0
    var updatedPrice = 0

    fun updateTotal() {
        this.value = updatedQty.times(updatedPrice)
    }

    addSource(quantity) { quantity ->
        updatedQty = quantity ?: 0
        updateTotal()
    }

    addSource(price) { price ->
        updatedPrice = price ?: 0
        updateTotal()
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...