Flow e ViewPager

João Victor
Android Dev BR
Published in
3 min readAug 21, 2020

Pessoal, hoje vamos ver um pouco como o Flow pode nos ajudar a fazer de uma forma elegante e bem mais organizada um carrossel.

Sabemos que existem várias maneiras de fazer o ViewPager alterar a posição baseado em um tempo pré-definido.

Poderíamos utilizar o Handler:

https://gist.github.com/jaozinfs/7f859796f6b364580c9f4e866c8ea444

Parece ótimo, nosso ViewPager está trocando de posição automaticamente. Mas e se nossa aplicação entrar em outro estado diferente de Lifecycle.ON_CREATE ?

Imagino que sua resposta foi : “ Cancelar nosso Timer“.

E de fato essa resposta não está errada, é sim uma boa opção, mas teríamos outros problemas futuramente.

Poderia passar despercebido e acabar manipulando errado a instância do timer, o que é uma dor de cabeça a mais que talvez você não precisa ter.

Outro ponto é o teste, a classe se torna um pouco mais difícil de ser testada, utilizando Handler e Timer.

Agora irei mostrar como fazer a implementação de uma forma diferente, utilizando Flow.

Kotlin Flow é uma nova API de processamento de stream desenvolvida pela JetBrains , a empresa por trás da linguagem Kotlin. É uma implementação da especificação Reactive Stream , uma iniciativa cujo objetivo é fornecer um padrão para processamento de stream assíncrono. A Jetbrains construiu o Kotlin Flow com base nas Kotlin Coroutines .

Vou mostrar um exemplo bem simples de como começar utilizar o Flow

https://gist.github.com/jaozinfs/9fa5cc920fdacfb246a192cad8d6bbc9

No exemplo acima, temos uma função onde retorna um Flow que irá emitir o valor atual e incrementar depois de um tempo definido no argumento da função.

Para coletar o Flow continua sendo bem simples:

https://gist.github.com/jaozinfs/d95c333d81ec6de3d34f4e805d5bd55a

Você precisa somente de um escopo para inicar um novo Job.

Com Flow, podemos manipular a instância antes de coletá-la. Como neste exemplo, onde vamos mapear e coletar somente os valores pares do produtor:

https://gist.github.com/jaozinfs/cffe63e17af403eb5f29b8d69dc1f9c1

Podemos também pegar somente os primeiros 10 valores emitidos:

https://gist.github.com/jaozinfs/cffe63e17af403eb5f29b8d69dc1f9c1

A grande sacada de utilizar o Flow para alterar a posição é que para coletar um Flow precisamos de um escopo, onde o flow será coletado. Quando o escopo é cancelado, seus Jobs filhos também são cancelados ! Ou seja, o escopo permanece vivo até que a atividade encerre seu ciclo de vida.

No Android, Fragment e Activity, por padrão tem como variável o lifeCycle que guarda nosso escopo “lifecycleScope”.

Quando o ciclo de vida da View chega ao fim, o lifecycleScope é cancelado sendo assim seus Jobs filhos serão automaticamente cancelados.

Assim não precisamos cancelar/manipular nosso Job manualmente !

Agora que sabemos um pouco mais sobre o Flow, vamos direto ao ponto.

Vamos criar nossa função que retorna um flow a partir de uma posição de start, uma posição final, e um tempo.

https://gist.github.com/jaozinfs/329522eeec677217c1004c53d6d7a0b1

Essa função retorna um Flow que emite um Inteiro, e vai rodar enquanto seu Job esta ativo

`coroutineContext[Job]?.isActive == true`

Agora vamos implementar em nosso ViewPager

https://gist.github.com/jaozinfs/3541c770dd6c4e9f1c8d12245b5696ba

E toda vez que alteramos a posição manualmente vamos reiniciar nosso flow, então vamos criar um Callback para nosso pager.

https://gist.github.com/jaozinfs/58dfff87b3486647996cfc0f693e2f8c

E voilà:

Bônus, com Flow quando o iniciamos o Job utilizando o lifecycleScope:

lifecycleScope.launchWhenCreated

Se o ciclo de vida for alterado para Lifecycle.ON_STOP, nosso coletor é suspendido até que o ciclo de vida seja retornado. Caso o ciclo de vida entre no Lifecycle.ON_DESTROY o emissor e coletor serão cancelados.

--

--