question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Flow's onCompletion not being called

See original GitHub issue

Hi,

As the guideline in https://codelabs.developers.google.com/codelabs/advanced-kotlin-coroutines/index.html?index=..%2F..index#13 suggests, the codelab is finished:

growZoneChannel.asFlow()
            .mapLatest { growZone ->
                _spinner.value = true
                if (growZone == NoGrowZone) {
                    plantRepository.tryUpdateRecentPlantsCache()
                } else {
                    plantRepository.tryUpdateRecentPlantsForGrowZoneCache(growZone)
                }
            }
            .onCompletion {
                _spinner.value = false
            }
            .catch { throwable ->
                _snackbar.value = throwable.message
            }
            .launchIn(viewModelScope) 

Even if you do the latest challenge to refactor all this, we would end up in this case:

init {
        // When creating a new ViewModel, clear the grow zone and perform any related udpates
        clearGrowZoneNumber()

        loadDataFor(growZoneChannel) { growZone ->
            _spinner.value = true
            if (growZone == NoGrowZone) {
                plantRepository.tryUpdateRecentPlantsCache()
            } else {
                plantRepository.tryUpdateRecentPlantsForGrowZoneCache(growZone)
            }
        }
    }

//where the loadDataFor is just:

private fun <T> loadDataFor(source: ConflatedBroadcastChannel<T>, block: suspend (T) -> Unit) {
        source.asFlow()
            .mapLatest {
                block(it)
            }
            .onCompletion {
                _spinner.value = false
            }
            .catch { throwable ->
                _snackbar.value = throwable.message
            }
            .launchIn(viewModelScope)
    }

However, the onCompletion method is not being called, and causing the _spinner value not to be updated at the end. I don’t know what’s wrong but I did try my solution and did try finished_code directory also.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:7
  • Comments:9

github_iconTop GitHub Comments

4reactions
khpproudcommented, Feb 15, 2020

I tried like this:

fun <T> loadDataFor(source: ConflatedBroadcastChannel<T>, block: suspend (T) -> Unit) {
        source.asFlow()
            .mapLatest {
                _spinner.value = true
                block(it)
            }
            .onEach { _spinner.value = false }
            .onCompletion { _spinner.value = false }
            .catch { _snackbar.value = it.message }
            .launchIn(viewModelScope)
}

The channel is not closed calling explicitly “close()” on viewModel’s lifecycle, so it seems more appropriate to add “onEach”.

1reaction
fegan104commented, Jan 26, 2020

You’re correct. I asked about this issue on Stackoverflow . Looks like the codelab is not correct when it states:

onCompletion will be called every time the flow above it completes. It’s the same thing as a finally block – it’s a good place to put any code you need to execute during cleanup. Here we’re resetting the spinner.”

Read more comments on GitHub >

github_iconTop Results From Across the Web

android - Why doesn't Flow.onCompletion get called for ...
When you run the Flow the spinner never disappears because onCompletion is never called even when the mapLatest transform completes.
Read more >
Not working onComletion after asFlow · Issue #2486 - GitHub
So in this case onCompletion will work only after canceling this cahnnel. But, we converted it to the Flow, so expected behavior is...
Read more >
onCompletion - Kotlin
Returns a flow that invokes the given actionafter the flow is completed or cancelled, passing the cancellation exception or failure as cause parameter...
Read more >
Flow lifecycle operations - Kt. Academy
Only the onCompletion handler will be called. The catch method stops an exception by catching it. The previous steps have already been completed,...
Read more >
onCompletion not called while using Koltin Flow with LiveData ...
if appDatabase.eventDao().getAllEvents() is based Room on Flow, never called onCompletion() . Why? Because getAllXXX() Query is 'Hot'.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found