Home > Net >  How to call a function from in ViewModel in viewModelScope?
How to call a function from in ViewModel in viewModelScope?

Time:12-16

In the repository class have this listener:

override fun getState(viewModelScope: CoroutineScope) = callbackFlow  {
    val listener = FirebaseAuth.AuthStateListener { auth ->
        trySend(auth.currentUser == null)
    }
    auth.addAuthStateListener(listener)
    awaitClose {
        auth.removeAuthStateListener(listener)
    }
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), auth.currentUser == null)

In my ViewModel class I call getState function that returns a StateFlow<Boolean> using:

fun getState() = repo.getState(viewModelScope)

And I collect the data:

setContent {
    val state = viewModel.getState().collectAsState().value
}

If I change in ViewModel:

fun getState() = viewModelScope.launch {
    repo.getState(this)
}

So it can be called from a viewModelScope, I cannot collect the data anymore, as .collectAsState() appears in red. How to solve this? Any help would be greatly appreciated.

CodePudding user response:

I'm not sure why you're trying to do this:

fun getState() = viewModelScope.launch {
    repo.getState(this)
}

This code launches an unnecessary coroutine (doesn't call any suspending or blocking code) that get's a StateFlow reference and promptly releases the reference, and the function itself returns a Job (the launched coroutine). When you launch a coroutine, the coroutine doesn't produce any returned value. It just returns a Job instance that you can use to wait for it to finish or to cancel it early.

Your repository function already creates a StateFlow that runs in the passed scope, and you're already passing it viewModelScope, so your StateFlow was already running in the viewModelScope in your original code fun getState() = repo.getState(viewModelScope).

CodePudding user response:

Use live data to send your result of state flow from view model to activity. In your view model do like this:

 var isActive = MutableLiveData<Boolean>();

    fun getState() {
    viewModelScope.launch {
        repo.getState(this).onStart {

        }
            .collect(){
                isActive.value = it;
            }
    }

}

In your activity observer your liveData like this:

 viewModel.isActive.observe(this, Observer {
                Toast.makeText(applicationContext,it.toString(),Toast.LENGTH_LONG).show()
            })

Hopefully it will help.

  • Related