Slide 1

Slide 1 text

Walmyr Carvalho #AndroidMeetupSP Android + Kotlin Coroutines Async de um jeito "diferente" +

Slide 2

Slide 2 text

Walmyr Carvalho @walmyrcarvalho

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Contexto

Slide 5

Slide 5 text

Aplicações modernas para Android vão precisar fazer uso de alguma operação assíncrona em algum momento.

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

E temos algumas várias (muitas) formas de se fazer isso, cada uma com um propósito:

Slide 8

Slide 8 text

AsyncTask Loader Service JobScheduler/JobSchedulerCompat IntentService Thread FutureTask Firebase JobDispatcher

Slide 9

Slide 9 text

E hoje temos uma biblioteca “vencedora” no que diz respeito a operações assíncronas no Android em geral.

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

Resumindo: Temos muitas opções mas todas elas tem algum ponto "negativo” em algum aspecto.

Slide 12

Slide 12 text

Kotlin Coroutines

Slide 13

Slide 13 text

Coroutines no Kotlin são threads "mais leves”, com uma sintaxe de código assíncrono tão direta quanto a de um código síncrono.

Slide 14

Slide 14 text

Elas são tipos de funções chamadas suspending functions, e tem seus métodos marcados com a palavra chave suspend.

Slide 15

Slide 15 text

suspend fun getUser(userId: String): User { // return an User object }

Slide 16

Slide 16 text

Na prática, a utilização duma coroutine seria:

Slide 17

Slide 17 text

// roda o código em uma thread pool em background fun asyncOverlay() = async(CommonPool) { // inicia duas operações assíncronas val original = asyncLoadImage("original") val overlay = asyncLoadImage("overlay") // e aplica o overlay para os dois resultados applyOverlay(original.await(), overlay.await()) } // executa a coroutine no contexto de UI launch(UI) { val image = asyncOverlay().await() showImage(image) }

Slide 18

Slide 18 text

O launch é a maneira mais simples de se criar uma coroutine numa thread em background, tendo um Job (uma task em background, basicamente) como sua referência para si.

Slide 19

Slide 19 text

public actual fun launch( context: CoroutineContext = DefaultDispatcher, start: CoroutineStart = CoroutineStart.DEFAULT, parent: Job? = null, block: suspend CoroutineScope.() -> Unit ): Job

Slide 20

Slide 20 text

Conceitualmente, o async é similar ao launch, mas a diferença deles é que o async retorna um Deferred, que é basicamente uma future (ou promise).

Slide 21

Slide 21 text

public actual fun async( context: CoroutineContext = DefaultDispatcher, start: CoroutineStart = CoroutineStart.DEFAULT, parent: Job? = null, block: suspend CoroutineScope.() -> T ): Deferred

Slide 22

Slide 22 text

O CoroutineContext diz respeito a qual thread ela irá rodar: background (CommonPool) ou UI.

Slide 23

Slide 23 text

Tecnicamente, um Deferred é um Job, só que com uma future com uma promessa de entregar um valor em breve.

Slide 24

Slide 24 text

Ou seja: No async você tem a mesma funcionalidade do launch, mas com a diferença que ele retorna um valor no .await():

Slide 25

Slide 25 text

fun getUser(userId: String): User = async { // return User } launch(UI) { val user = getUser(id).await() navigateToUserDetail(user) }

Slide 26

Slide 26 text

Também é possível rodar alguma operação bloqueando completamente a thread, utilizando o runBlocking, mas não é algo muito necessário no Android:

Slide 27

Slide 27 text

runBlocking { delay(2000) }

Slide 28

Slide 28 text

Resumindo: Se não faço questão de um callback -> launch Se eu preciso esperar uma future (Deferred) -> async Se eu preciso bloquear minha thread -> runBlocking

Slide 29

Slide 29 text

Também é possível cancelar um Job (ou um Deferred), e checar o estado dele:

Slide 30

Slide 30 text

val job = launch { // do your stuff } job.cancel() val job = launch { while (isActive){ //do your stuff } }

Slide 31

Slide 31 text

Configurando no seu projeto

Slide 32

Slide 32 text

dependencies { classpath 'com.android.tools.build:gradle:3.0.1' classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.30' } build.gradle

Slide 33

Slide 33 text

dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.30" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.5" implementation “org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.5" } app/build.gradle

Slide 34

Slide 34 text

kotlin { experimental { coroutines "enable" } } app/build.gradle

Slide 35

Slide 35 text

Exemplos de uso no Android

Slide 36

Slide 36 text

Kotlin Coroutines for Retrofit github.com/gildor/kotlin-coroutines-retrofit

Slide 37

Slide 37 text

fun Call.await(): T

Slide 38

Slide 38 text

fun main(args: Array) = runBlocking { try { val user: User = api.getUser("username").await() println("User ${user.name} loaded") } catch (e: HttpException) { println("exception${e.code()}", e) } catch (e: Throwable) { println("Something broken", e) } }

Slide 39

Slide 39 text

Retrofit 2 Coroutine Adapter (Experimental) - Jake Wharton github.com/JakeWharton/retrofit2-kotlin-coroutines-adapter

Slide 40

Slide 40 text

val retrofit = Retrofit.Builder() .baseUrl("https://example.com/") .addCallAdapterFactory(CoroutineCallAdapterFactory()) .build()

Slide 41

Slide 41 text

interface MyService { @GET("/user") fun getUser(): Deferred // ou @GET("/user") fun getUser(): Deferred> }

Slide 42

Slide 42 text

PEKO (PErmissions in KOtlin) github.com/JakeWharton/retrofit2-kotlin-coroutines-adapter

Slide 43

Slide 43 text

launch (UI) { val result = Peko.requestPermissions(this, Manifest.permission.BLUETOOTH).await() if (result.grantedPermissions.contains(Manifest.permission.BLUETOOTH)) { // permissão concedida } else { // nope } }

Slide 44

Slide 44 text

Dúvidas?

Slide 45

Slide 45 text

Links úteis

Slide 46

Slide 46 text

Coroutines - Documentação Oficial kotlinlang.org/docs/reference/coroutines.html

Slide 47

Slide 47 text

Deep Dives into Coroutines on JVM - Roman Elizarov (KotlinConf 2017) goo.gl/Vt22LK

Slide 48

Slide 48 text

Community - Kotlin kotlinlang.org/community/

Slide 49

Slide 49 text

Kotlin - Android Developers developer.android.com/kotlin

Slide 50

Slide 50 text

Kotlin Meetup SP meetup.com/kotlin-meetup-sp

Slide 51

Slide 51 text

Android Dev BR slack.androiddevbr.org

Slide 52

Slide 52 text

Muito obrigado!