是否可以在没有附加变量的情况下增加 mutablelivedata?

Is it possible to increment mutablelivedata without additional variable?

我有一个带有编辑文本和 2 个按钮的简单视图,我想让用户能够使用按钮将 increse/decrese 数量增加 1,或者他可以在编辑文本小部件中手动写入数量,但是这个值不能小于 0 且大于 10。我将 MVVM 架构与 LiveData 和数据绑定一起使用。目前在 ViewModel 中我有两个变量 _amount: Intamount:MutableLiveData。我是 incrmenting/decrementing _amount 然后将新值分配给 MutableLiveData。它正在工作,但我想知道是否可以仅使用一个变量来存储数量即 amount:MutableLiveData

来获得相同的结果 视图模型
class TestActivityVM : ViewModel() {

    val amount = MutableLiveData<String>()
    private var _amount = 0

    init {
        amount.value = _amount.toString()
    }

    fun increment() {
        Log.d("TestActivityVM", "The amount is being increment, current value = ${amount.value}")

        //increment amount value by 1 if amount is less than 10
        if(_amount < 10) {
            amount.value = (++_amount).toString()
        }
    }

    fun decrement() {
        Log.d("TestActivityVM", "The amount is being decrement, current value = ${amount.value}")

        //decrement amount value by 1 if amount is greater than 0
        if(_amount > 0) {
            amount.value = (--_amount).toString()
        }
    }

    val amountValidator: TextWatcher = object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
            _amount = if(s.toString().isEmpty()) 0 else s.toString().toInt()

            if(_amount > 10) {
                _amount = 10
                amount.value = _amount.toString()
            }
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        }

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
        }

    }
}
Activity
class TestActivity : AppCompatActivity() {

    private lateinit var testBinding: ActivityTestBinding
    private lateinit var testVM: TestActivityVM

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        testVM = ViewModelProviders.of(this).get(TestActivityVM::class.java)

        testBinding = DataBindingUtil.setContentView<ActivityTestBinding>(this, R.layout.activity_test).also {
            it.lifecycleOwner = this
            it.testVM = testVM
        }
    }
}
布局
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="testVM"
            type=".TestActivityVM" />
    </data>


    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".TestActivity">

        <Button
            android:id="@+id/minusBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="16dp"
            android:text="-"
            android:onClick="@{() -> testVM.decrement()}"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/amountET" />

        <Button
            android:id="@+id/plusBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="8dp"
            android:text="+"
            android:onClick="@{() -> testVM.increment()}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/amountET" />

        <EditText
            android:id="@+id/amountET"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:ems="10"
            android:inputType="numberSigned"
            android:text="@={testVM.amount}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:addTextChangedListener="@{testVM.amountValidator}"/>

        <TextView
            android:id="@+id/textView4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="84dp"
            android:text="Value of amount Live data:"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/minusBtn" />

        <TextView
            android:id="@+id/textView5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="32dp"
            android:layout_marginTop="8dp"
            android:text="@{testVM.amount}"
            android:textSize="24sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView4" />

    </android.support.constraint.ConstraintLayout>
</layout>

将数量更改为类型 MutableLiveData

fun increment() {
    Log.d("TestActivityVM", "The amount is being increment, current value = ${amount.value}")

    //increment amount value by 1 if amount is less than 10
    if(amount.value!! < 10) amount.value = amount.value!! +1
}

fun decrement() {
    Log.d("TestActivityVM", "The amount is being decrement, current value = ${amount.value}")

    //decrement amount value by 1 if amount is greater than 0
    if(amount.value!! > 0) {
        amount.value = amount.value!! -1
    }
}

您可以使用 amount.value 来获取当前金额,而不是使用另一个变量。 LiveData 应该是 Int,而不是 String,因为这是您要处理的数据类型。您的代码可能如下所示:

class TestActivityVM : ViewModel() {

    val amount = MutableLiveData<Int>().apply {
        value = 0
    }

    fun increment() {
        Log.d("TestActivityVM", "The amount is being increment, current value = ${amount.value}")

        //increment amount value by 1 if amount is less than 10
        amount.value?.let { a ->
            if (a < 10) {
                amount.value = a + 1
            }
        }
    }

理想的推荐方法是在 activity 中观察不可变的 livedata 对象。 不是从 VM 观察可变变量,而是创建一些返回 liveddata 的方法,这样 activity 不应该修改可变对象。

同时避免在 VM 中使用 Android 组件/API 以使 VM 可测试。