Home > Enterprise >  Waiting for coroutine finish before fragment close
Waiting for coroutine finish before fragment close

Time:10-24

In my View Model I have created a function that uploads audio file to Firebase Storage.Then I want to close my fragment but only if the file was already uploaded so I have to wait for coroutine to complete job. How can I achieve it? I can use runBlocking and it works but I don't think that's a good idea.

fun addRequest(request: Event){
    scope.launch {
        val uri = repository.uploadAudioFile()
        request.audio = uri
        repository.addRequest(request)
    }
}

Then in my fragment I want to call something like:

 prosbyViewModel.addRequest(Event(title = title,description = description, date = date))
 requireActivity().supportFragmentManager.popBackStack()

CodePudding user response:

You can make the function that launches a coroutine return the Job, so you can wait for it in other coroutines:

fun addRequest(request: Event): Job = viewModelScope.launch {
    val uri = repository.uploadAudioFile()
    request.audio = uri
    repository.addRequest(request)
}

Then, in your Fragment, you can join() the job in another coroutine, so you're waiting for it without blocking the main thread. I think you probably want to freeze other UI, so you may want to set up your layout so it can disable your UI when it reaches this state.

viewLifecycle.lifecycleScope.launch {
    disableTheUi()
    prosbyViewModel.addRequest(Event(title = title,description = description, date = date))
        .join()
    requireActivity().supportFragmentManager.popBackStack()
}

Alternatively, you can make it a suspend function to begin with so it is always called from a coroutine and waited for without the need for join():

suspend fun addRequest(request: Event) {
    val uri = repository.uploadAudioFile()
    request.audio = uri
    repository.addRequest(request)
}

One possible way to disable the whole UI would be to change your fragment's layout so the top level view is a FrameLayout containing your original layout, plus one more layout that shows a indeterminate progress bar. To disable the UI, set the original layout's top view to invisible, and set the progress bar's layout to visible.

CodePudding user response:

You might think about doing your upload in the background, not in the viewmodel itself.

The currently suggested way of doing this is via workmanager, see https://developer.android.com/topic/libraries/architecture/workmanager

WorkManager is the recommended solution for persistent work. Work is persistent when it remains scheduled through app restarts and system reboots. Because most background processing is best accomplished through persistent work, WorkManager is the primary recommended API for background processing.

  • Related