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

Kotlin State & Shared Flows in Action

Mohit S
July 27, 2021

Kotlin State & Shared Flows in Action

Shared Flow APIs

Mohit S

July 27, 2021
Tweet

More Decks by Mohit S

Other Decks in Programming

Transcript

  1. Kotlin State & Shared Flows in Action • State Flow

    • Shared Flow • Broadcast Channel vs shared flow • Convert cold streams to shared flows • Buffer Overflow Strategies
  2. What is a cold stream? A cold stream is a

    flow that triggers the same code every time it is collected.
  3. Cold Flows val flow = flowOf(1, 2, 3) 
 .map

    { it + 1 } flow.collect { ... }
  4. Cold Flows val flow = flowOf(1, 2, 3) 
 .map

    { it + 1 } flow.collect { ... }
  5. Cold Flows val flow = flowOf(1, 2, 3) 
 .map

    { it + 1 } flow.collect { ... }
  6. Cold Flows val flow = flowOf(1, 2, 3) 
 .map

    { it + 1 } flow.collect { // 2, 3, 4 }
  7. Cold Flows val flow = flowOf(1, 2, 3) 
 .map

    { it + 1 } flow.collect { ... } flow.collect { ... }
  8. Cold Flows val flow = flowOf(1, 2, 3) 
 .map

    { it + 1 } flow.collect { ... } flow.collect { ... }
  9. Cold Flows val flow = flowOf(1, 2, 3) 
 .map

    { it + 1 } flow.collect { ... } flow.collect { // 2, 3, 4 }
  10. What is a hot stream? A hot stream is a

    flow whose active instance exists independently 
 of the presence of collectors.
  11. State Flow sealed class UiState { 
 data class Error(

    
 val exception: Throwable 
 ): UiState() }
  12. State Flow sealed class UiState { 
 data class Success(

    val data: Data ): UiState() data class Error( 
 val exception: Throwable 
 ): UiState() }
  13. State Flow sealed class UiState { 
 data class Success(

    val data: Data ): UiState() data class Error( 
 val exception: Throwable 
 ): UiState() }
  14. State Flow val uiState = MutableStateFlow( . .. ) uiState.collect

    { ... } 
 
 uiState.collect { ... } Latest value is received
  15. State Flow Conflation val uiState = MutableStateFlow( . .. )

    uiState.value = UIState.Success( .. . ) 
 
 uiState.value = UIState.Error( .. . ) Conflate
  16. State Flow Conflation val uiState = MutableStateFlow( . .. )

    uiState.value = UIState.Success( .. . ) 
 
 uiState.value = UIState.Error( .. . ) 
 
 uiState.collect { ... } Error
  17. State Flow vs Live Data State Flow Live Data Default

    Value Unsubscribe 
 (Stopped State)
  18. State Flow vs Live Data State Flow Live Data Default

    Value Unsubscribe 
 (Stopped State)
  19. State Flow vs Live Data State Flow Live Data Default

    Value Unsubscribe 
 (Stopped State)
  20. State Flow Summary • How to setup state flow •

    Emit and collect • State Flow vs Live Data
  21. Shared Flow val flow = MutableSharedFlow<String>() 
 launch { delay(2000);

    flow.collect { } } launch { flow.emit("Event 1”) }
  22. Shared Flow val flow = MutableSharedFlow<String>() 
 launch { delay(2000);

    flow.collect { } } launch { flow.emit("Event 1”) }
  23. Shared Flow val flow = MutableSharedFlow<String>() 
 launch { delay(2000);

    flow.collect { } } No value is received launch { flow.emit("Event 1”) }
  24. Shared Flow val flow = MutableSharedFlow<String>() 
 launch { flow.emit("Event

    1”) } launch { delay(2000); flow.collect { } } Replay
  25. Shared Flow val flow = MutableSharedFlow<String>(replay = 1) 
 launch

    { flow.emit("Event 1”) } launch { delay(2000); flow.collect { } }
  26. Shared Flow val flow = MutableSharedFlow<String>(replay = 1) 
 launch

    { delay(2000); flow.collect { } } launch { flow.emit("Event 1”) } Event 1
  27. val flow = MutableSharedFlow<String>(replay = 1) 
 Shared Flow State

    Flow launch { flow.collect { } } launch { flow.subscriptionCount.value }
  28. Shared Flow val flow = MutableSharedFlow<String>(replay = 1) 1 Subscriber

    launch { flow.collect { } } launch { flow.subscriptionCount.value }
  29. Shared Flow val flow = MutableSharedFlow<String>(replay = 1) Shared Flow

    does not complete normally launch { flow.collect { } }
  30. Cold Flows val flow = flowOf(1, 2, 3) 
 flow

    .onCompletion { } .collect { ... } Flow completes normally
  31. Shared Flow val flow = MutableSharedFlow<String>(replay = 1) val job

    = launch { flow.onCompletion { }.collect { } } job.cancel() Flow completes exceptionally
  32. While Subscribed • Active as long as external scope is

    alive • Remains as long as there are collectors.
  33. Properties Active as long as external scope is alive sharedFlow.collect

    { } externalScope.cancel() Complete Exceptionally
  34. Properties Remains as long as there are collectors. val sharedFlow

    = flow.onCompletion { }.shareIn(…) val job = launch { sharedFlow.onCompletion { }.collect { } }
  35. Properties Remains as long as there are collectors. val sharedFlow

    = flow.onCompletion { }.shareIn(…) val job = launch { sharedFlow.onCompletion { }.collect { } } job.cancel()
  36. Properties Remains as long as there are collectors. val sharedFlow

    = flow.onCompletion { }.shareIn(…) val job = launch { sharedFlow.onCompletion { }.collect { } } job.cancel()
  37. Properties Remains as long as there are collectors. val sharedFlow

    = flow.onCompletion { }.shareIn(…) val job = launch { sharedFlow.onCompletion { }.collect { } } job.cancel()
  38. Properties Remains as long as there are collectors. val sharedFlow

    = flow.onCompletion { }.shareIn(…) val job1 = launch { sharedFlow.collect { } } val job2 = launch { sharedFlow.collect { } }
  39. Properties Remains as long as there are collectors. val sharedFlow

    = flow.onCompletion { }.shareIn(…) job1.cancel() val job2 = launch { sharedFlow.collect { } }
  40. Properties Remains as long as there are collectors. val sharedFlow

    = flow.onCompletion { }.shareIn(…) job1.cancel() val job2 = launch { sharedFlow.collect { } } Remain Active
  41. Properties • Active as long as external scope is alive

    • Remains as long as there are collectors.
  42. Eagerly Start producer eagerly and never stop flow .onStart {

    println("ON START") } .shareIn( ... started = SharingStarted.Eagerly)
  43. Eagerly Start producer eagerly and never stop flow .onStart {

    println("ON START") } .shareIn( ... started = SharingStarted.Eagerly)
  44. Eagerly Start producer eagerly and never stop flow .onStart {

    println("ON START") } .shareIn( ... started = SharingStarted.Eagerly) ON START
  45. Eagerly Start producer eagerly and never stop flow .onComplete {

    println("ON COMPLETE”) } .shareIn( ... started = SharingStarted.Eagerly)
  46. Eagerly Start producer eagerly and never stop flow .onComplete {

    println("ON COMPLETE”) } .shareIn( ... started = SharingStarted.Eagerly) externalScope.cancel()
  47. Eagerly Start producer eagerly and never stop flow .onComplete {

    println("ON COMPLETE”) } .shareIn( ... started = SharingStarted.Eagerly) Never stops externalScope.cancel()
  48. Sharing Policies • While Subscribed • Active while there are

    active subscribers. 
 • Eagerly • Start producer eagerly and never stop 
 • Lazily • Start after the first subscriber appears and never stop
  49. Buffering Overflow Strategies val flow = MutableSharedFlow<String>( extraBufferCapacity = 2,

    onBufferOverflow = BufferOverflow.SUSPEND ) Buffer + Replay Count
  50. Kotlin State & Shared Flows in Action • State Flow

    • Shared Flow • Broadcast Channel vs shared flow • Convert cold streams to shared flows • Buffer Overflow Strategies