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..
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 } }
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!!"
}
}
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()
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.