Scamparelli
Scamparelli

Reputation: 744

How to Return LiveData from Repository

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

Answers (3)

Sandesh Baliga
Sandesh Baliga

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.

  1. Activity class: Change makeToast method to observeCurrentName() like this:

    private fun observeCurrentName() {
        vm.getCurrentName().observe(this, Observer{ 
            //Toast here 
        })
    }
    
  2. Your VM:

    class LoginViewModel : ViewModel() {
        ...
    
        fun getCurrentName(): MutableLiveData<String>{
            return repository.getCurrentName()
        }
    
        fun setCurrentName(name: String?){
            repository.setCurrentName(name)
        }
    
        ...
    }
    
  3. 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

Md. Asaduzzaman
Md. Asaduzzaman

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

John O&#39;Reilly
John O&#39;Reilly

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

Related Questions