Fluxo Kotlin | Parte 2
Neste artigo, entenderemos o fluxo do Kotlin em detalhes.
Já está publicada a PARTE 1 deste artigo que pode visitar a partir daqui.
Fluxo Kotlin | Parte 1Esta é a PARTE 2 da série que cobre os seguintes tópicos:
- Cancelamento de Fluxo
- Operadores de fluxo intermediário
- Operador de transformação
- Operador de limitação de tamanho
- Operador de Fluxo Terminal
Em Kotlin, cancelamento de fluxo é o processo de interromper a execução de um fluxo quando ele não é mais necessário. Isso pode ser útil para evitar vazamentos de recursos e cálculos desnecessários.
Para cancelar um fluxo, você pode usar a cancel()função. Essa função é definida como uma função de extensão na Jobinterface, que é retornada pela launch()função quando você inicia uma co-rotina. Portanto, para cancelar um fluxo, você precisa ter uma referência ao Jobobjeto que foi retornado quando o fluxo foi lançado.
Aqui está um exemplo de como cancelar um fluxo:
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking<Unit> {
val flow = flow {
for (i in 1..10) {
delay(100)
emit(i)
}
}
val job = launch {
flow.collect { println(it) }
}
delay(500)
job.cancel()
}
Após 500 milissegundos, chamamos a cancel()função no Jobobjeto retornado por launch(). Isso cancela o fluxo e interrompe quaisquer outras emissões. A co-rotina que estava coletando os valores de fluxo será cancelada e o programa será finalizado.
Observe que quando um fluxo é cancelado, o cancelamento é propagado a montante para a origem do fluxo. Neste exemplo, a delay()função dentro do fluxo lançará um CancellationException, que será capturado pela co-rotina que iniciou o fluxo.
Outras maneiras de cancelar o fluxo usando verificações de cancelamento de fluxo
- Loop ocupado emitindo valores canceláveis
fun foo(): Flow<Int> = flow {
for (i in 1..5) {
println("Emitting $i")
emit(i)
}
}
fun main() = runBlocking<Unit> {
foo().collect { value ->
if (value == 3) cancel()
println(value)
}
}
Emitting 1
1
Emitting 2
2
Emitting 3
3
Emitting 4
Exception in thread "main" kotlinx.coroutines.JobCancellationException: BlockingCoroutine was cancelled; job="coroutine#1":BlockingCoroutine{Cancelled}@6d7b4f4c
fun main() = runBlocking<Unit> {
(1..5).asFlow().collect { value ->
if (value == 3) cancel()
println(value)
}
}
1
2
3
4
5
Exception in thread "main" kotlinx.coroutines.JobCancellationException: BlockingCoroutine was cancelled; job="coroutine#1":BlockingCoroutine{Cancelled}@3327bd23\
Outra forma de cancelar um fluxo é usar o cancellable()operador para tornar o fluxo cancelável de fora. Aqui está um exemplo:
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking<Unit> {
val flow = flow {
for (i in 1..10) {
delay(100)
emit(i)
}
}
val job = launch {
flow.cancellable().collect { println(it) }
}
delay(500)
job.cancel()
}
Observe que o cancellable()operador na verdade não cancela o fluxo; simplesmente torna possível cancelar o fluxo de fora. O fluxo só será cancelado se a corrotina que está coletando os valores do fluxo também for cancelada.
Operadores de fluxo intermediário
Os fluxos podem ser transformados usando operadores, da mesma forma que você transformaria coleções e sequências. Operadores intermediários são aplicados a um fluxo a montante e retornam a um fluxo a jusante. Esses operadores são frios, assim como os fluxos. Uma chamada para tal operador não é uma função de suspensão em si. Funciona rapidamente, retornando a definição de um novo fluxo transformado.
filter:
val numbers = flowOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// filter out even numbers
val filteredNumbers = numbers.filter { it % 2 == 0 }
filteredNumbers.collect { println(it) } // output: 2 4 6 8 10
O mapoperador transforma elementos em um fluxo usando uma função especificada. Por exemplo, você pode usar o mapoperador para converter temperaturas de Fahrenheit para Celsius.
val temperaturesFahrenheit = flowOf(68, 73, 82, 79, 64, 57)
val temperaturesCelsius = temperaturesFahrenheit.map { (it - 32) * 5/9 }
temperaturesCelsius.collect { println(it) }
// output: 20.0 22.77777777777778 27.77777777777778 26.11111111111111 17.77777777777778 13.88888888888889
O flatMapConcatoperador transforma cada elemento de um fluxo em outro fluxo e concatena os fluxos resultantes em um único fluxo de saída. Por exemplo, você pode usar o flatMapConcatoperador para ler vários arquivos CSV e concatenar seu conteúdo em um único fluxo.
val filenames = flowOf("file1.csv", "file2.csv", "file3.csv")
// read each file and concatenate their contents into a single flow
val contents = filenames.flatMapConcat { filename ->
flow {
// read contents of the file
val fileContents = readFile(filename)
// emit each line of the file as a separate element in the flow
fileContents.lines().forEach { emit(it) }
}
}
contents.collect { println(it) } // output: contents of file1.csv, contents of file2.csv, contents of file3.csv
O distinctUntilChangedoperador remove elementos duplicados consecutivos de um fluxo. Por exemplo, você pode usar o distinctUntilChangedoperador para remover valores duplicados consecutivos de um fluxo de inteiros.
val numbers = flowOf(1, 2, 2, 3, 3, 3, 2, 2, 1)
// remove consecutive duplicates
val distinctNumbers = numbers.distinctUntilChanged()
distinctNumbers.collect { println(it) } // output: 1 2 3 2 1
O takeoperador limita o número de elementos em um fluxo a um máximo especificado. Por exemplo, você pode usar o takeoperador para limitar o número de elementos em um fluxo para 5.
val numbers = flowOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// limit to 5 elements
val limitedNumbers = numbers.take(5)
limitedNumbers.collect { println(it) } // output: 1 2 3 4 5
o transformoperador é usado para transformar os elementos emitidos por um Flow para produzir um novo Flow.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking<Unit> {
val numbers = flowOf(1, 2, 3, 4, 5)
numbers
.transform { value ->
emit("Value: $value")
emit("Double value: ${value * 2}")
}
.collect { println(it) }
}
Value: 1
Double value: 2
Value: 2
Double value: 4
Value: 3
Double value: 6
Value: 4
Double value: 8
Value: 5
Double value: 10
No fluxo Kotlin, existem vários operadores que podem ser usados para limitar o tamanho dos itens emitidos no fluxo.
O cancelamento em corrotinas é sempre realizado lançando uma exceção, para que todas as funções de gerenciamento de recursos (como try { ... } finally { ... }blocos) operem normalmente em caso de cancelamento.
take(n: Int): este operador pega os primeirosnelementos do fluxo e cancela o fluxo. Se o fluxo produzir menos denelementos, ele emitirá todos eles.takeWhile(predicate: (T) -> Boolean): Este operador obtém elementos do fluxo enquanto a função de predicado retornatrue. Quando o predicado retornafalse, o fluxo é cancelado.takeLast(n: Int): Este operador coleta os últimosnelementos emitidos pelo fluxo e os emite na ordem inversa.
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.takeLast
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val numbers = flowOf(1, 2, 3, 4, 5)
val lastThreeNumbers = numbers.takeLast(3)
lastThreeNumbers.collect { println(it) } // prints 3, 4, 5
}
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val numbers = flowOf(1, 2, 3, 4, 5)
numbers.drop(2).collect { println(it) } // prints 3, 4, 5
}
Operador de Fluxo Terminal
Operadores de terminal são operadores em Kotlin Flow que consomem os elementos emitidos pelo fluxo e produzem um resultado. coletar é o mais usado.
toList(): Este operador coleta todos os elementos emitidos pelo fluxo em uma lista e retorna a lista.toSet(): Este operador coleta todos os elementos emitidos pelo fluxo em um conjunto e retorna o conjunto.reduce(): Este operador aplica uma determinada função aos elementos emitidos pelo fluxo e retorna um único valor. A função recebe dois argumentos, sendo o primeiro o resultado acumulado até o momento e o segundo o próximo elemento emitido pelo fluxo.fold(): Este operador é semelhante aoreduce(), mas permite especificar um valor inicial para o resultado acumulado.count(): Este operador conta o número de elementos emitidos pelo fluxo e retorna a contagem como um inteiro.min(),max(): Esses operadores encontram o elemento mínimo ou máximo emitido pelo fluxo, respectivamente.collect(): Este operador consome os elementos emitidos pelo fluxo e executa uma ação em cada elemento. Ele não retorna um resultado, mas é frequentemente usado para efeitos colaterais.
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val numbers = flowOf(1, 2, 3, 4, 5)
val list = numbers.toList()
println("List of numbers: $list")
val set = numbers.toSet()
println("Set of numbers: $set")
val sum = numbers.reduce { accumulator, value -> accumulator + value }
println("Sum of numbers: $sum")
val product = numbers.fold(1) { accumulator, value -> accumulator * value }
println("Product of numbers: $product")
val count = numbers.count()
println("Count of numbers: $count")
val min = numbers.min()
println("Minimum number: $min")
val max = numbers.max()
println("Maximum number: $max")
numbers.collect { println("Processing $it") }
}
List of numbers: [1, 2, 3, 4, 5]
Set of numbers: [1, 2, 3, 4, 5]
Sum of numbers: 15
Product of numbers: 120
Count of numbers: 5
Minimum number: 1
Maximum number: 5
Processing 1
Processing 2
Processing 3
Processing 4
Processing 5
Em conclusão, o Kotlin Flow é uma ferramenta poderosa para criar aplicativos reativos e assíncronos em Kotlin. Sua capacidade de lidar com fluxos de dados e sua integração com corrotinas o tornam uma excelente opção para lidar com operações assíncronas e gerenciar atualizações de interface do usuário. Com seu rico conjunto de operadores e API fácil de usar, os desenvolvedores podem criar facilmente pipelines de dados complexos que podem lidar com uma ampla variedade de cenários. O Kotlin Flow fornece uma maneira simples, concisa e intuitiva de gerenciar fluxos de dados em seus aplicativos Kotlin, tornando-o uma adição valiosa ao kit de ferramentas de qualquer desenvolvedor. Como o Kotlin continua a ganhar popularidade como linguagem de escolha para o desenvolvimento do Android, o Kotlin Flow certamente se tornará uma ferramenta indispensável para a criação de aplicativos robustos, eficientes e responsivos.
Espero que este artigo tenha sido útil para você.
Se você tiver algum comentário ou dúvida, escreva-me de volta para [email protected]. Suas palmas são muito apreciadas para ajudar outras pessoas a encontrar este artigo .





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)