How to wait for a suspend function to call a non-suspend function in one after another

45 Views Asked by At

I have the following method in my viewModel which calls a suspend usecase.

fun clearFirebaseCache() {
    viewModelScope.launch {
        clearFirebaseCacheUseCase.execute()
    }
}

And in my MainActivity it is called like this:

mMainViewModel.changeLanguageConsumableLiveData
    .observeAndConsume(this) {
        lifecycleScope.launch {
            mMainViewModel.clearFirebaseCache()
            ProcessPhoenix.triggerRebirth(this@MainActivity)
        }
    }

As the clearFirebaseCache() has to complete first before calling ProcessPhoenix.triggerRebirth I have added a Deferred so that I can wait for it to finish first.

However, I don't like having this Deferred<Unit> and would prefer a launch as it just clears the cache and returns nothing.

I think it should be in a launch as its not returning anything just a one time call. But as I have to run these in sequence I don't know any other way.

Another thing, having this Deferred makes it more messy as if I want to use this anywhere else I always have to call await, even if I don't have any calls to make in sequence.

This is the final solution

Take in a lamba that will be called after cleared cache

fun clearFirebaseCache() {
    viewModelScope.launch {
        clearFirebaseCacheUseCase.execute()
    }
}

And using it like this, not sure if this is a good pattern or not.

mMainViewModel.changeLanguageConsumableLiveData
    .observeAndConsume(this) {
        lifecycleScope.launch {
            mMainViewModel.clearFirebaseCache(waitUntilComplete = {
                ProcessPhoenix.triggerRebirth(this@MainActivity)
            })
        }
    }
1

There are 1 best solutions below

6
broot On BEST ANSWER

Waiting for a suspend function to finish is a default behavior when calling it, we don't need any deferreds, launch(), etc.:

suspend fun clearFirebaseCache(): Unit {
    clearFirebaseCacheUseCase.execute()
}

Then:

mMainViewModel.clearFirebaseCache()
ProcessPhoenix.triggerRebirth(this@MainActivity)

As simple as that.

Your approach with Deferred or a callback should work as well, but this is the traditional solution and coroutines were invented specifically to replace such patterns with a better alternative. As we can see in the example above, the code greatly simplifies by using a suspend function and calling it directly.