Reputation: 744
I just can't see how to chain LiveData from Repo to VM, so I have tried to boil this down to the most simple of example!:
Fragment
class LoginFragment : Fragment() {
private lateinit var loginViewModel: LoginViewModel
private var mCurrentName = "Blank!"
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val binding: LoginFragmentBinding = DataBindingUtil.inflate(
inflater, R.layout.login_fragment, container, false)
binding.apply {
loginButton.setOnClickListener{
loginViewModel.changeText()
}
}
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
loginViewModel = ViewModelProviders.of(this).get(LoginViewModel::class.java)
loginViewModel.getCurrentName().observe(viewLifecycleOwner, Observer {
mCurrentName = it // I'm expecting mCurrentName to equal "Button Clicked!" when button clicked..
makeToast() // Toast works, but variable remains unchanged..
})
}
private fun makeToast() {
Toast.makeText(activity, mCurrentName, Toast.LENGTH_LONG).show()
}
ViewModel
class LoginViewModel : ViewModel() {
private val firestoreRepository : FirestoreRepository = FirestoreRepository()
private var mCurrentName = MutableLiveData<String>()
fun changeText(){
mCurrentName = firestoreRepository.changeText()
}
Repository
class FirestoreRepository {
private val mCurrentName = MutableLiveData<String>()
fun changeText(): MutableLiveData<String> {
mCurrentName.value = "Button Clicked!!"
return mCurrentName
}
I'm assuming I have misunderstood how the observer function works..
Upvotes: 0
Views: 3989
Reputation: 663
Actually If you are maintaining LiveData
in repository, I don't think there's a need of separate LiveData
in ViewModel
as well. You just have to observe the LiveData once from the activity. Then make any changes to repository instance directly. So If I have to show it in your code, It might look something like this.
Activity class: Change makeToast method to observeCurrentName() like this:
private fun observeCurrentName() {
vm.getCurrentName().observe(this, Observer{
//Toast here
})
}
Your VM:
class LoginViewModel : ViewModel() {
...
fun getCurrentName(): MutableLiveData<String>{
return repository.getCurrentName()
}
fun setCurrentName(name: String?){
repository.setCurrentName(name)
}
...
}
Your repository:
class FirestoreRepository {
private val mCurrentName = MutableLiveData<String>()
fun getCurrentName(): MutableLiveData<String>{
return mCurrentName
}
fun setCurrentName(name: String?){
mCurrentName.value = name //This will trigger observer in Activity
}
}
Upvotes: 3
Reputation: 15423
No need to change MutableLiveData
inside ViewModel
. Try to pass whatever Repository
send to View
. Check below
class LoginViewModel : ViewModel() {
private val firestoreRepository : FirestoreRepository = FirestoreRepository()
fun getCurrentName(): MutableLiveData<String> {
return firestoreRepository.getCurrentName()
}
fun changeText() {
firestoreRepository.changeText()
}
}
And also your FirestoreRepository
class FirestoreRepository {
private val mCurrentName = MutableLiveData<String>()
fun getCurrentName(): MutableLiveData<String> {
return mCurrentName
}
fun changeText() {
mCurrentName.value = "Button Clicked!!"
}
}
Upvotes: 1
Reputation: 10330
You're changing mCurrentName
(the LiveData variable itself as opposed to it's contents) after you start observing it. The guidance seems to be to not use LiveData
in Repository layer (use Coroutines/Flow instead for example)....but for now you could have something like following (or perhaps use one of the LiveData Transformations)
private val mCurrentName = firestoreRepository.currentName()
fun changeText(){
firestoreRepository.changeText()
}
Upvotes: 0