Migração de Kotlin Coroutines experimentais para a versão estável

Tempo de leitura: 2 minutes

Kotlin Coroutines, embora já bastante estáveis como livres de bugs e prontas para uso em código de produção, foram consideradas experimentais, o que significava que sua API poderia mudar a qualquer momento. E assim foi: o Kotlin 1.3 foi lançado, a coroutines foram promovidas ao status estável e a API mudou um pouco, então, se você desenvolveu no Kotlin 1.2 usando coroutines experimentais versões anteriores à 1.0, como fiz em todos os meus aplicativos, você precisará fazer alguns ajustes.

Vamos passar por algumas das principais mudanças.

Remova “experimental” das importações

Isso é bastante óbvio: como a coroutines perderam seu status experimental, os nomes dos pacotes mudaram. Você precisará ajustar as importações de:

import kotlinx.coroutines.experimental.*

Para

import kotlinx.coroutines.*

Em vez de lançar em um escopo global, o escopo local agora é o padrão

Enquanto em estado experimental, quando você lançou uma nova coroutine, ela foi lançada em um escopo global e poderia sobreviver ao próprio componente em que foi lançada, conforme descrito neste problema.

Este comportamento foi alterado: as coroutines agora são iniciadas em um escopo local por padrão, o que significa que está vinculado ao tempo de vida do escopo: se o componente morrer, a coroutine também morrerá.

Para manter o comportamento antigo na nova API, você precisa mudar de:

launch { doSomething() }

Para:

GlobalScope.launch { doSomething()

No entanto, você realmente deve pensar sobre qual deve ser o tempo de vida apropriado e o escopo de cada coroutine que você iniciar. Por exemplo, se uma coroutine muda os elementos da IU do componente em que foi lançada, não faz sentido que ela esteja no GlobalScope, e pode falhar se o componente morrer enquanto a coroutine está ativa: seu tempo de vida deve ser o mesmo que (ou menos do que) os elementos da IU que toca.

 

CommonPool, UI e outros despachantes têm novos nomes

Para lançar uma coroutine em um pool compartilhado de threads que não podem tocar a IU nem o IO, você fez uma vez:

launch(CommonPool) { doSomething() }

Em vez de CommonPool, agora você deve usar Dispatchers.Default:

GlobalScope.launch(Dispatchers.Default) { doSomething() }

(Observe que já estou ajustando o escopo com GlobalScope para manter o mesmo comportamento, conforme explicado na seção acima)

Ou, como você já poderia fazer com CommonPool, você pode omitir o parâmetro dispatcher completamente:

GlobalScope.launch { doSomething() }

Em vez de usar o UI dispatcher para permitir operações de UI nas coroutines, você deve usar Dispatchers.Main. Então, o velho

launch(UI) { doSomething() }

Torna-se:

GlobalScope.launch(Dispatchers.Main) { doSomething() }

O dispatcher IO agora é denominado Dispatchers.IO.

 

Mudanças também se aplicam a atores

Os atores do Kotlin são legais – eles capacitam as coroutines com processamento sequencial.

Sua API seguiu todas as alterações de API descritas acima. Mais ainda, parece que a API de atores complexos atualmente está obsoleta e seu futuro é desconhecido, conforme descrito nesta edição. Então, depois de ajustar seus atores, você pode se beneficiar de anotá-los (e todas as outras funções que os usam) com:

@ObsoleteCoroutinesApi

E às vezes com

@ExperimentalCoroutinesApi

Como sugerido pelo Android Studio.