Flow e ViewPager
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:
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
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:
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:
Podemos também pegar somente os primeiros 10 valores emitidos:
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.
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
E toda vez que alteramos a posição manualmente vamos reiniciar nosso flow, então vamos criar um Callback para nosso pager.
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.