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

Using Kotlin Flow in MVVM

Using Kotlin Flow in MVVM

LiveData was never designed to be a full-fledged reactive stream. Thread management with LiveData is very hard and making data transformation with transformation operators is very limited. Moreover, testing LiveData becomes very tricky and is likely to open for race conditions if you are using it with coroutines.

Luckily, Kotlin Flow provides asynchronously computed values with the power of Coroutines. Making data transformations becomes very easy with Flow intermediate operators. Furthermore, StateFlow provides caching the current state just like LiveData. Since there is a back-pressure in Flow, unit testing is much simpler with handy Flow terminal operators.

Kotlin Flow is a very powerful reactive stream with its robust operators. Using Flow instead of LiveData makes it easier to handle data transformations and background processes. Finally, testing Flow is much safer and painless compared to LiveData.

Fatih Giriş

October 21, 2021
Tweet

More Decks by Fatih Giriş

Other Decks in Programming

Transcript

  1. Using Kotlin Flow in MVVM
    S. Fatih Giris
    Android Lead @ DNB Bank
    fgiris fatih_grs

    View full-size slide

  2. Sample
    https://github.com/fgiris/LiveDataWithFlowSample

    View full-size slide

  3. Agenda
    • LiveData in MVVM
    • LiveData + Flow
    • Only Flow
    • Testing

    View full-size slide

  4. LiveData in MVVM
    • LiveData
    ✓Lifecycle aware
    ✓No memory leak
    ✓Cache
    ✓…

    View full-size slide

  5. LiveData in MVVM
    • LiveData
    - Backpressure ❌
    Producer
    Observer
    Ref: https://github.com/Froussios/Intro-To-RxJava/blob/master/Part%204%20-%20Concurrency/4.%20Backpressure.md

    View full-size slide

  6. LiveData in MVVM
    • LiveData
    - Backpressure ❌
    - Data transformation 🥵

    View full-size slide

  7. LiveData in MVVM
    • LiveData
    - Backpressure ❌
    - Data transformation ❌
    - Requires lifecycle owner to observe (Activity, Fragment …) 🤔

    View full-size slide

  8. LiveData in MVVM
    • Weather forecast app
    • One-shot request
    • Data stream

    View full-size slide

  9. LiveData in MVVM
    • ViewModel: LiveData
    • Repository: Suspend
    Ref: https://developer.android.com/jetpack/guide

    View full-size slide

  10. LiveData in MVVM
    WeatherForecastRepository.kt

    View full-size slide

  11. LiveData in MVVM
    WeatherForecastRepository.kt

    View full-size slide

  12. LiveData in MVVM
    WeatherForecastViewModel.kt

    View full-size slide

  13. LiveData in MVVM
    WeatherForecastViewModel.kt

    View full-size slide

  14. LiveData in MVVM
    WeatherForecastViewModel.kt

    View full-size slide

  15. LiveData in MVVM
    WeatherForecastViewModel.kt

    View full-size slide

  16. LiveData in MVVM
    WeatherForecastViewModel.kt

    View full-size slide

  17. Return multiple
    values?

    View full-size slide

  18. LiveData in MVVM
    Open Twitter app

    View full-size slide

  19. LiveData in MVVM
    Open Twitter app
    Get the tweets from
    cache

    View full-size slide

  20. LiveData in MVVM
    Open Twitter app
    Get the tweets from
    cache
    Fetch new tweets from
    server
    Update UI

    View full-size slide

  21. LiveData in MVVM
    Open Twitter app
    Get the tweets from
    cache
    Fetch new tweets from
    server
    Update UI

    View full-size slide

  22. LiveData in MVVM
    WeatherForecastRepository.kt

    View full-size slide

  23. LiveData in MVVM
    WeatherForecastRepository.kt

    View full-size slide

  24. Flow
    • Reactive stream which can return asynchronously
    computed values

    View full-size slide

  25. Flow
    Pros
    • Structured concurrency
    • Cold stream
    • Efficient data transformation
    • Easy testing

    View full-size slide

  26. LiveData + Flow
    • ViewModel: LiveData
    • Repository: Flow
    Ref: https://developer.android.com/jetpack/guide

    View full-size slide

  27. LiveData + Flow
    WeatherForecastRepository.kt

    View full-size slide

  28. LiveData + Flow
    WeatherForecastRepository.kt

    View full-size slide

  29. LiveData + Flow
    WeatherForecastOneShotViewModel.kt

    View full-size slide

  30. LiveData + Flow
    WeatherForecastOneShotViewModel.kt
    Flow

    View full-size slide

  31. LiveData + Flow
    WeatherForecastOneShotViewModel.kt
    Flow

    View full-size slide

  32. LiveData + Flow
    WeatherForecastOneShotFragment.kt

    View full-size slide

  33. LiveData + Flow
    WeatherForecastRepository.kt

    View full-size slide

  34. LiveData + Flow
    WeatherForecastRepository.kt
    Data per second

    View full-size slide

  35. LiveData + Flow
    WeatherForecastDataStreamViewModel.kt

    View full-size slide

  36. Flow
    Intermediate Flow Operators
    • map
    • filter
    • transform
    • onEach
    • …

    View full-size slide

  37. LiveData + Flow
    map operator

    View full-size slide

  38. LiveData + Flow
    map operator

    View full-size slide

  39. LiveData + Flow
    map operator

    View full-size slide

  40. LiveData + Flow
    onStart operator

    View full-size slide

  41. LiveData + Flow
    filter operator

    View full-size slide

  42. LiveData + Flow
    onEach operator

    View full-size slide

  43. LiveData + Flow
    flowOn operator

    View full-size slide

  44. LiveData + Flow
    catch operator

    View full-size slide

  45. LiveData + Flow
    asLiveData extension

    View full-size slide

  46. Why not only Flow?

    View full-size slide

  47. LiveData 👋

    View full-size slide

  48. Flow
    • Cold stream
    • ≠ LiveData
    • Configuration changes 🙄

    View full-size slide

  49. Flow
    WeatherForecastDataStreamFlowViewModel.kt
    😭

    View full-size slide

  50. Flow
    WeatherForecastDataStreamFlowViewModel.kt
    No asLiveData

    View full-size slide

  51. Flow
    WeatherForecastDataStreamFlowFragment.kt

    View full-size slide

  52. Flow
    WeatherForecastDataStreamFlowFragment.kt
    Terminal Operator
    👈

    View full-size slide

  53. Flow
    WeatherForecastDataStreamFlowFragment.kt

    View full-size slide

  54. Testing
    • LiveData
    • LiveData & Coroutines might result some race condition
    • Need to observe again when Transformations used

    View full-size slide

  55. Testing
    • Flow
    • Sequential
    • No race condition
    • Test like a list (toList )

    View full-size slide

  56. Testing
    WeatherForecastRepository.kt

    View full-size slide

  57. Testing
    WeatherForecastRepositoryTest.kt

    View full-size slide

  58. Testing
    WeatherForecastRepositoryTest.kt

    View full-size slide

  59. Testing
    WeatherForecastRepositoryTest.kt

    View full-size slide

  60. Testing
    WeatherForecastRepositoryTest.kt

    View full-size slide

  61. Testing
    WeatherForecastRepositoryTest.kt

    View full-size slide

  62. Testing
    WeatherForecastRepositoryTest.kt

    View full-size slide

  63. Testing
    WeatherForecastRepositoryTest.kt

    View full-size slide

  64. Testing
    Dispatchers.Main -> Android Main Looper -> Android OS

    View full-size slide

  65. Testing
    Solution: TestCoroutineDispatcher

    View full-size slide

  66. Testing
    MainCoroutineRule.kt

    View full-size slide

  67. Testing
    MainCoroutineRule.kt

    View full-size slide

  68. Testing
    MainCoroutineRule.kt

    View full-size slide

  69. TL;DR
    • Flow & LiveData similar
    • One shot request
    • Repository: Suspend or Flow
    • ViewModel: LiveData or Flow (with repeatOnLifecycle in the View layer)
    • Data stream
    • Repository: Flow
    • ViewModel: LiveData or Flow (with repeatOnLifecycle in the View layer)
    • LiveData Tests 😥 - Flow Tests 😎

    View full-size slide

  70. https://medium.com/@girisfth
    Missed something?

    View full-size slide

  71. QUESTIONS
    @fatih_grs

    View full-size slide

  72. References
    • https://proandroiddev.com/using-livedata-flow-in-mvvm-part-i-
    a98fe06077a0

    • https://proandroiddev.com/using-livedata-flow-in-mvvm-part-
    ii-252ec15cc93a

    • https://github.com/fgiris/LiveDataWithFlowSample

    • https://developer.android.com/topic/libraries/architecture/livedata

    • https://proandroiddev.com/when-not-to-use-livedata-6a1245b054a6

    • https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/
    kotlinx.coroutines.flow/index.html

    View full-size slide

  73. References
    • https://medium.com/@elizarov/kotlin-flows-and-
    coroutines-256260fb3bdb

    • https://github.com/Kotlin/kotlinx.coroutines/pull/1354

    • https://codelabs.developers.google.com/codelabs/
    advanced-kotlin-coroutines/

    • https://medium.com/androiddevelopers/unit-testing-livedata-
    and-other-common-observability-problems-bb477262eb04

    • https://medium.com/swlh/kotlin-coroutines-in-android-unit-
    test-28ff280fc0d5

    View full-size slide