I have simple view with edit text and 2 buttons and I want to give user ability to increse/decrese amount by 1 with buttons or he can manually write amount in edit text widget, but this value can't be less than 0 and greater than 10. I'm using MVVM architecture with LiveData and databinding. Currently in ViewModel I've two variables _amount: Int
and amount:MutableLiveData
. I'm incrmenting/decrementing _amount
and then assign new value to MutableLiveData. It's working but I'm wondering if it is possible to achive same result using only one variable to store amount i.e 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
}
}
}
Layout
<?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>
You can use amount.value
to get the current amount, instead of using another variable. The LiveData should be of Int, not String, as that's the data type you're dealing with. Here's how your code could look like:
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
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With