Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

614
Visualizações
Flow onEach/collect gets called multiple times when back from Fragment

I'm using Flow instead of LiveData to collect data in my Fragment. In Fragment A I observe (or rather collect) the data in my fragment`s onViewCreated like this:

lifecycleScope.launchWhenStarted {
            availableLanguagesFlow.collect {
                languagesAdapter.setItems(it.allItems, it.selectedItem)
            }
        }

Problem. Then when I go to Fragment B and then comes back to Fragment A, my collect function gets called twice. If I go the Fragment B again and back to A - then collect function is called 3 times. And so on.

over 4 years ago · Hanz Gallego
2 Respostas
Responde à pergunta

0

Use SharedFlow and apply replayCache to it.

Resets the replayCache of this shared flow to an empty state. New subscribers will be receiving only the values that were emitted after this call, while old subscribers will still be receiving previously buffered values. To reset a shared flow to an initial value, emit the value after this call. more information

private val _reorder = MutableSharedFlow<ViewState<ReorderDto?>>().apply {
    resetReplayCache()
}
val reorder: SharedFlow<ViewState<ReorderDto?>>
    get() = _reorder
over 4 years ago · Hanz Gallego Relatório

0

Reason

It happens because of tricky Fragment lifecycle. When you come back from Fragment B to Fragment A, then Fragment A gets reattached. As a result fragment's onViewCreated gets called second time and you observe the same instance of Flow second time. Other words, now you have one Flow with two observers, and when the flow emits data, then two of them are called.

Solution 1 for Fragment

Use viewLifecycleOwner in Fragment's onViewCreated. To be more specific use viewLifecycleOwner.lifecycleScope.launch instead of lifecycleScope.launch. Like this:

viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            availableLanguagesFlow.collect {
                languagesAdapter.setItems(it.allItems, it.selectedItem)
            }
        }

Solution 2 for Activity

In Activity you can simply collect data in onCreate.

lifecycleScope.launchWhenStarted {
            availableLanguagesFlow.collect {
                languagesAdapter.setItems(it.allItems, it.selectedItem)
            }
        }

Additional info

  1. Same happens for LiveData. See the post here. Also check this article.
  2. Make code cleaner with Kotlin extension:

extension:

fun <T> Flow<T>.launchWhenStarted(lifecycleOwner: LifecycleOwner) {
    lifecycleOwner.lifecycleScope.launchWhenStarted {
        this@launchWhenStarted.collect()
    }
}

in fragment onViewCreated:

availableLanguagesFlow
    .onEach {
        //update view
    }.launchWhenStarted(viewLifecycleOwner)

Update

I'd rather use now repeatOnLifecycle, because it cancels the ongoing coroutine when the lifecycle falls below the state (onStop in my case). While without repeatOnLifecycle, the collection will be suspended when onStop. Check out this article.

fun <T> Flow<T>.launchWhenStarted(lifecycleOwner: LifecycleOwner)= with(lifecycleOwner) {
    lifecycleScope.launch {
        repeatOnLifecycle(Lifecycle.State.STARTED){
            try {
                this@launchWhenStarted.collect()
            }catch (t: Throwable){
                loge(t)
            }
        }
    }
}
over 4 years ago · Hanz Gallego Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda