'How do you observe LiveData outside a fragment
I have a TextView inside a Fragment. Using LiveData I am able to change the text from within the fragment. By using a button in the MainActivity (outside the fragment) I am trying to change the text in the TextView, but it is not working. Can someone help. Here is my code:
This is the MainActivity which has a button and a fragment
class MainActivity : AppCompatActivity() {
var tg: ToneGenerator? = null
private lateinit var btn: Button
private lateinit var viewModel:ViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tg = ToneGenerator(AudioManager.STREAM_SYSTEM, 100)
btn = findViewById(R.id.buttonTest1)
viewModel = ViewModelProvider(this).get(ViewModel::class.java)
btn.setOnClickListener {
tg?.startTone(ToneGenerator.TONE_PROP_BEEP)
viewModel.changeMLD()
}
}
}
This is the fragment which has a TextView
class Fragment : Fragment() {
private lateinit var txt1: TextView
public lateinit var viewModel:ViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view: View = inflater.inflate(R.layout.fragment, container, false)
txt1 = view.findViewById(R.id.txt1)
viewModel = ViewModelProvider(this).get(ViewModel::class.java)
viewModel.initiateMLD()
viewModel.LD.observe(viewLifecycleOwner, Observer {
txt1.setText("Count is "+it)
})
return view
}
}
This is the ViewModel with the LiveData
class ViewModel : ViewModel(){
private var clickCount:Int = 0
private var MLD = MutableLiveData<Int>()
var LD : LiveData<Int> = getMLD() // observer watches this variable
fun initiateMLD(){
MLD.value = 5
clickCount = 5
}
fun getMLD():MutableLiveData<Int>{
return MLD
}
fun changeMLD(){
clickCount+=2
MLD.value = clickCount
}
}
Solution 1:[1]
In your fragment you've created viewModel using your fragment as the owner,
viewModel = ViewModelProvider(this).get(ViewModel::class.java)
Whereas to communicate with the activity you need to create viewModel object using activity as the owner. These are called sharedViewModels.
ViewModelProvider(requireActivity()).get(ViewModel::class.java)
You can read more about SharedViewModel in this codelab tutorial.
Solution 2:[2]
You are using 2 different instances of ViewModel. ViewModelProvider creates one for your activity and one for your fragment. It is because they both are viewModelStoreOwners. If you want to use the same instance of ViewModel in both Fragment and Activity. It has to be activity scoped. You can do that like this
ViewModelProvider(requireActivity()).get(ViewModel::class.java)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Praveen |
| Solution 2 | dtunctuncer |
