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
}
}
CodePudding user response:
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.
CodePudding user response:
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)