Tecnologia

Introdução ao Kotlin Coroutines

Por: , maio 18, 2018

Basicamente Coroutines oferece uma maneira de escrever códigos assíncronos de forma sequencialmente em uma co-rotina, permitindo que você se livre do famigerado Callback Hell em seu código, possibilitando um código mais compacto, fácil de gerenciar e alterar.

Quem está familiarizado com C# possivelmente já conhece async/await, coroutines oferece um conceito próximo a isso, porém de forma mais robusta, porque no lugar de uma simples implementação específica da ideia, é um recurso da linguagem que pode ser utilizado de maneiras diferentes para resolver problemas diferentes.

Uma ferramenta muito comum utilizada para chamadas assíncronas no desenvolvimento Android é o RxJava juntamente com o Retrofit. O RxJava fornece uma ótima alternativa para o desenvolvimento assíncrono, porém não te livra da criação de callbacks definidos pelo método subscribe()

Abaixo um exemplo de como é comumente feita uma chamada para uma API usando RxJava:

repository.remoteCall()
                   .subscribeOn(Schedulers.io())
                   .observeOn(AndroidSchedylers.mainThread())
                   .subscribe(callbackSucess, callbackError)

Por mais funcional que o RxJava seja para manipular fluxos e encadear operações assíncronas podemos notar alguns problemas:

– Necessidade de criar sempre dois callbacks de sucesso e erro definidos no método subscribe(). Supondo que no projeto você tenha cerca de 100 casos de uso (um cenário comum no mundo real) , serão inúmeros métodos de retorno espalhados pelo código, imagine o quanto de métodos de retornos terá que percorrer para realmente encontrar o que está procurando;

– Dificuldade em criar códigos modulares e legíveis quando é preciso compor os resultados de dois ou mais casos de uso;

– Fluxo difícil de ler devido a API’s fluentes. Em fluxos complexos torna-se difícil de ler e/ou modificar devido a uma cadeia de operadores muito extensa, o que é praticamente obrigatório para lidar com fluxos;

Utilizando Coroutines

Podemos ver a seguir as principais features do kotlin coroutines que podem resolver alguns dos problemas citados anteriormente. Abaixo um exemplo de uma simples chamada utilizando coroutines:

button.setOnClickListener {

   launch(UI) {
        val userString = fetchUserString(“1”).await()
        val user = deserializeUser(userString).await()
        showUserData(user)
{

}

Coroutines são baseados em funções de suspensão (suspending functions), os métodos marcados com a palavra reservada suspend podem suspender a execução de uma co-rotina sem bloquear a thread.

suspend fun fetchUserData(userId: String): String { // return user String }

Funções de suspensão só podem ser chamadas por coroutines ou em outras funções de suspensão. Normalmente encontradas como parâmetro lambda em funções da biblioteca coroutines como launch() ou async().

No primeiro exemplo é usado a função await() que também pode ser uma função de suspenção (por isso chamado dentro de um launch()), que suspende uma co-rotina até que receba algum retorno esperado.

launch{}

Launch é a função mais simples do coroutines utilizada caso você não precise de valores de retorno:

launch {
      val userString = fetchUserString(“1”)
      val user = deserializeUser(userString)
      log(user.name)
}

launch retorna um Job que pode ser usado em outras co-rotinas para controlar sua execução, como por exemplo cancelar:

val job = launch { // do work }
job.cancel()

async{}

O async possui o mesmo comportamento que o launch com a diferença de que pode retornar um valor:

val user = async {
                    val userString = fetchUserString(“1”)
                    val user = deserializeUser(userString)
                   user
         }.await()

A função async() retorna um Defered<T>() que representa o retorno que será recebido quando o valor terminar de ser computado e que permite utilizar o método await(). O deferend também é um Job então você pode cancelar também caso precise.

Kotlin Coroutines ainda é experimental, isso significa que pode sofrer algumas mudanças ainda, mas já possui recursos muito estáveis, que como vimos fornece uma maneira compacta de resolver os problemas mais comuns ao se trabalhar com softwares assíncronos, o que não é uma tarefa fácil. Este artigo arranha apenas a superfície do que você pode fazer com coroutines, sem abordar assuntos mais complexos, como por exemplo, os recursos de baixo nível para criadores de bibliotecas, o que fiz foi apenas uma introdução ao que pode ser feito com esse recurso.

Se caso deseje saber mais sobre o Coroutines, você pode encontrar mais informações na documentação oficial .

Referências:

https://proandroiddev.com/android-coroutine-recipes-33467a4302e9

https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md#composing-suspending-functions

  • Receba nosso conteúdo em primeira mão.