是否可以在没有附加变量的情况下增加 mutablelivedata?
Is it possible to increment mutablelivedata without additional variable?
我有一个带有编辑文本和 2 个按钮的简单视图,我想让用户能够使用按钮将 increse/decrese 数量增加 1,或者他可以在编辑文本小部件中手动写入数量,但是这个值不能小于 0 且大于 10。我将 MVVM 架构与 LiveData 和数据绑定一起使用。目前在 ViewModel 中我有两个变量 _amount: Int
和 amount: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 可测试。
我有一个带有编辑文本和 2 个按钮的简单视图,我想让用户能够使用按钮将 increse/decrese 数量增加 1,或者他可以在编辑文本小部件中手动写入数量,但是这个值不能小于 0 且大于 10。我将 MVVM 架构与 LiveData 和数据绑定一起使用。目前在 ViewModel 中我有两个变量 _amount: Int
和 amount: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 可测试。