【问题标题】:How to update UI from model business logic?如何从模型业务逻辑更新 UI?
【发布时间】:2020-09-14 05:24:25
【问题描述】:

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

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

我正在使用 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)
   }
}

视图模型

    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 中找不到类似的逻辑。

【问题讨论】:

    标签: android kotlin android-livedata android-architecture-components mutablelivedata


    【解决方案1】:

    我认为您可以按照 google 的 codelabs 指南进行数据绑定。

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

    简而言之,您可以使用 LiveData 来更新视图。这样在你的viewmodel中应该是这样的

    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
    

    点击链接示例了解更多详情

    【讨论】:

      【解决方案2】:

      在 viewModel 中将实例作为 LiveData

      val instance = MutableLiveData<Detail>()
      
      fun addQuantity(){
           instance.value.quantity.add(1)
      }
      
      fun addPrice(){
           instance.value.price.add(1)
      }
      

      在 Fragment/Activity 中确保添加此行进行绑定

      binding.lifecycleOwner = viewLifecycleOwner
      

      确保你有这个库可以使用viewLifecycleOwner

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

      【讨论】:

        【解决方案3】:

        是的,你的直觉是正确的。 LiveData 专属于ViewModel,但不限于ViewModels。这是 MVVM 架构方法,建议在 ViewModels 中使用 LiveData

        无论如何,假设您有两个名为quantityprice 的实时数据。现在,如果 total 依赖于这两个实时数据,那么您可以将其设为 MediatorLiveData,然后观察这两个属性以确保当两者都可用时始终反映结果(已更改)。 p>

        下面的例子是你如何做到的:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-04-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-06
          • 2020-09-07
          相关资源
          最近更新 更多