Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Android Assíncrono

Android Assíncrono

Apresentada na trilha Android do TDC São Paulo 2018

2dc2a52d38ee8c184deeceaadf9ed6ba?s=128

Rafael Toledo

July 18, 2018
Tweet

More Decks by Rafael Toledo

Other Decks in Programming

Transcript

  1. ANDROID ASSÍNCRONO De RxJava a Coroutines e WorkManager

  2. /_rafaeltoledo /rafaeltoledo

  3. O PROBLEMA DO ASSINCRONISMO 3

  4. "Eu adoro código assíncrono, nunca dá problema!" 4

  5. "Eu adoro código assíncrono, nunca dá problema!" Ninguém, 2018 5

  6. Por que é um problema? 6 • Diminui a legibilidade

    do código • Mais difícil de debugar • Pode trazer problemas de concorrência • Pode trazer problemas de desempenho
  7. lifecycle 7

  8. lifecycle 8

  9. Abordagens "clássicas" e seus problemas 9 • AsyncTask - dificuldade

    em lidar com lifecycle, facilidade em causar leaks de memória • IntentService - API verbosa e a necessidade de se criar um serviço para cada tarefa (ou uma tarefa com muita lógica) • Threads - pouco controle (ou controle demais?)
  10. RXJAVA 10

  11. RxJava - o que é? 11 • Biblioteca parte das

    Reactive Extensions • Mais que uma biblioteca de assincronismo • Introduz paradigmas de programação reativa funcional • Tem uma curva de aprendizado íngreme
  12. Ah, mas você tá usando RxJava, me explica aí como

    funciona 12
  13. 13

  14. RxJava - quando eu uso? 14 • Múltiplas fontes de

    dados que precisam ser trabalhadas juntas • Fluxo contínuo de dados • UI dinâmica (reativa)
  15. KOTLIN COROUTINES 15

  16. Kotlin Coroutines - o que é? 16 • Desde o

    Kotlin 1.1 • Permite escrever código assíncrono de forma sequencial • Evita complexidade • Evita o famoso "callback hell"
  17. Kotlin Coroutines - quando eu uso? 17 • Processamento assíncrono

    fora da main thread ◦ Requests ◦ I/O ◦ Processamento • kotlinx-coroutines-android permite fazer a mudança para a main thread!
  18. Kotlin Coroutines 18 // Expectativa fun performRequest() { view.showLoading() val

    result = api.fetch() view.hideLoading() textView.setText(result.data) }
  19. 19

  20. Kotlin Coroutines 20 fun performRequest() = launch(UI) { view.showLoading() val

    result = withContext(CommonPool) { api.fetch() } view.hideLoading() textView.setText(result.data) }
  21. Kotlin Coroutines 21 fun performRequest() = launch(UI) { view.showLoading() val

    result = withContext(CommonPool) { api.fetch() } view.hideLoading() textView.setText(result.data) }
  22. Kotlin Coroutines 22 fun performRequest() = launch(UI) { view.showLoading() val

    result = withContext(CommonPool) { api.fetch() } view.hideLoading() textView.setText(result.data) }
  23. Kotlin Coroutines 23 fun performRequest() = launch(UI) { view.showLoading() val

    result = withContext(CommonPool) { api.fetch() } view.hideLoading() textView.setText(result.data) }
  24. Kotlin Coroutines - Contextos 24 • UI: executa na main

    thread • CommonPool: executa em uma thread em background • Unconfined: executa na mesma thread
  25. Kotlin Coroutines 25 fun performRequest() = launch(UI) { view.showLoading() //

    Joga exception...? val result = withContext(CommonPool) { api.fetch() } view.hideLoading() textView.setText(result.data) }
  26. 26

  27. Kotlin Coroutines 27 fun performRequest() = launch(UI) { view.showLoading() try

    { val result = withContext(CommonPool) { api.fetch() } textView.setText(result.data) } catch (exception: IOException) { textView.setText(exception.message) } view.hideLoading() }
  28. Kotlin Coroutines - Deferred 28 interface API { fun fetch():

    Deferred<Response> { // ... } }
  29. Kotlin Coroutines 29 fun performRequest() = async(UI) { view.showLoading() try

    { val task = async(CommonPool) { api.fetch() } val result = task.await() textView.setText(result.data) } catch (exception: IOException) { textView.setText(exception.message) } view.hideLoading() }
  30. Kotlin Coroutines 30 fun performRequest() = async(UI) { view.showLoading() try

    { val task = async(CommonPool) { api.fetch() } val result = task.await() textView.setText(result.data) } catch (exception: IOException) { textView.setText(exception.message) } view.hideLoading() }
  31. Mas eu ainda uso Java no meu projeto... 31

  32. 32

  33. WORKMANAGER 33

  34. WorkManager - quando usar? Tarefas "adiáveis" - precisam ser executadas,

    mesmo se o app for fechado, mas não precisam ser executadas em um momento exato É uma solução consistente semelhante ao JobScheduler Ex: upload de logs, sincronização com servidor, tarefas de processamento pesado, que podem demorar bastante 34
  35. WorkManager Utiliza em sua implementação JobScheduler, Firebase JobDispatcher ou AlarmManager

    // Atualmente na versão 1.0.0-alpha04 android.arch.work:work-runtime :work-runtime-ktx :work-testing :work-firebase 35
  36. WorkManager - API 36 class FirstWorker : Worker() { override

    fun doWork(): Result { TODO() } }
  37. WorkManager - API 37 class FirstWorker : Worker() { override

    fun doWork(): Result { return Result.SUCCESS } }
  38. WorkManager - API 38 class FirstWorker : Worker() { override

    fun doWork(): Result { return Result.FAILURE } }
  39. WorkManager - API 39 class FirstWorker : Worker() { override

    fun doWork(): Result { return Result.RETRY } }
  40. WorkManager - API 40 class FirstWorker : Worker() { override

    fun doWork(): Result { inputData applicationContext } }
  41. WorkManager - Agendamento Simples 41 val firstWork = OneTimeWorkRequest.Builder(FirstWorker::class.java) .build()

    WorkManager.getInstance()?.enqueue(firstWork)
  42. WorkManager - Agendamento Simples 42 val firstWork = OneTimeWorkRequest.Builder(FirstWorker::class.java) .build()

    WorkManager.getInstance()?.enqueue(firstWork)
  43. WorkManager - Agendamento Simples 43 val firstWork = OneTimeWorkRequestBuilder<FirstWorker>() .build()

    WorkManager.getInstance()?.enqueue(firstWork)
  44. WorkManager - Agendamento Simples 44 val firstWork = OneTimeWorkRequestBuilder<FirstWorker>() .setInputData(Data.Builder()

    .putString("key", "value") .build()) .build() WorkManager.getInstance()?.enqueue(firstWork)
  45. WorkManager - Agendamento Simples 45 val firstWork = OneTimeWorkRequestBuilder<FirstWorker>() .setInputData(mapOf("value"

    to "key").toWorkData()) .build() WorkManager.getInstance()?.enqueue(firstWork) // Dentro do método doWork() inputData.getString("key", "Default Value")
  46. WorkManager - Constraints 46 val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .setRequiresCharging(true)

    .setRequiresBatteryNotLow(true) .build() val firstWork = OneTimeWorkRequestBuilder<FirstWorker>() .setConstraints(constraints) .setInputData(mapOf("value" to "key").toWorkData()) .build()
  47. WorkManager - Constraints 47 val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .setRequiresCharging(true)

    .setRequiresBatteryNotLow(true) .build() val firstWork = OneTimeWorkRequestBuilder<FirstWorker>() .setConstraints(constraints) .setInputData(mapOf("value" to "key").toWorkData()) .build()
  48. WorkManager - Agendamento Periódico 48 // work-runtime-ktx val periodicWork =

    PeriodicWorkRequestBuilder<FirstWorker>(1, TimeUnit.DAYS).build() WorkManager.getInstance()?.enqueue(periodicWork)
  49. WorkManager - Testes 49 @Before fun setUp() { WorkManagerTestInitHelper.initializeTestWorkManager( InstrumentationRegistry.getTargetContext())

    // ... } @Test fun checkIfJobIsDone() { val worker = ... WorkManager.getInstance()?.enqueue(worker) WorkManagerTestInitHelper.getTestDriver().setAllConstraintsMet(worker.id) // Assertions }
  50. Worker - outras possibilidades • Encadear workers • Paralelizar workers

    • Executar workers com delay 50
  51. Worker - pontos importantes • é executado após o sistema

    obter um wakelock - não é necessário requisitar • é executado numa thread em background • não deve iniciar nenhuma nova thread - deve retornar um status • não pode rodar pra sempre - ~10 minutos 51
  52. Links KOTLIN COROUTINES https://github.com/Kotlin/kotlinx.coroutines A GUIDE TO KOTLIN COROUTINES BY

    EXAMPLE https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md WORKMANAGER https://developer.android.com/topic/libraries/architecture/workmanager 52
  53. Links - vídeos INTRODUCTION TO COROUTINES https://www.youtube.com/watch?v=_hfBv0a09Jc DEEP DIVE INTO

    COROUTINES ON JVM https://www.youtube.com/watch?v=YrrUCSi72E8 EASY BACKGROUND PROCESSING WITH WORKMANAGER https://www.youtube.com/watch?v=IrKoBFLwTN0 53
  54. OBRIGADO Para perguntas ou sugestões: Rafael Toledo rdtoledo@thoughtworks.com speakerdeck.com/rafaeltoledo 54