How to pass editText value to viewModel and Livedata (Kotlin)
Asked Answered
V

1

8

I'm studying Android + Kotlin and make a simple example to understand LiveData + ViewModel. It's very simple: I have one root activity and two fragments. FragmentOne has two EditTexts. That values are summed and I need to pass the result to a ViewModel. Then I use observe in both root activity and FragmentTwo to see the changed data.

FragmentOne

class FragmentOne: Fragment() {
   private val model by lazy { ViewModelProviders.of(activity).get(MyViewModel::class.java) }
   var resultSum:Int = 0

   override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
     val view = inflater?.inflate(R.layout.fragment_one,container,false)
     val btn = view?.findViewById<Button>(R.id.sendToModel)
     btn?.setOnClickListener({
         val field1 = n1.text.toString().toInt()
         val field2 = n2.text.toString().toInt()
         resultSum = field1 + field2
         model.update()
     })
     return view
  }
}

viewModel

class MyViewModel: ViewModel() {
   private val fragment by lazy {FragmentOne()}
   private var _result = MutableLiveData<Int>().apply { value = 0 }
   val result: LiveData<Int>
      get() = _result

   fun update(){
       _result.value = fragment.resultSum
   }
}

Observer root activity

private val resultModel by lazy {ViewModelProviders.of(this).get(MyViewModel::class.java)}
resultModel.result.observe(this, Observer { result -> resultTxt.text = result.toString()})

Observer FragmentTwo

private val resultModel by lazy {ViewModelProviders.of(activity).get(MyViewModel::class.java)}
resultModel.result.observe(this, Observer { result -> resultTxt.text = result.toString()})

I checked var resultSum (Log) and It hold Int value from sum. The observer is working too (if I instantiate result.value inside ViewModel, the value is observable to activity and fragment)

I appreciate any help.

Visitation answered 12/6, 2018 at 19:17 Comment(0)
C
12

ViewModel should not have any reference to Android.* libraries. So you having a reference to FragmentOne is a bad practice.

A cleaner approach is to change the update() function to accept a String -

 fun update(result: String){
        _result.value = result
    }

And change your FragmentOne code to say -

btn?.setOnClickListener({
    val field1 = n1.text.toString().toInt()
    val field2 = n2.text.toString().toInt()
    resultSum = field1 + field2
    model.update(resultSum)
})
Chiao answered 12/6, 2018 at 20:16 Comment(1)
Nice tip about string, @karthik. I remembered to read something about references in viewModel. That's what it's all about. Thx again.Visitation

© 2022 - 2024 — McMap. All rights reserved.