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

Effective Multiplatform Architecture

Effective Multiplatform Architecture

Building multiplatform apps requires thinking about architecture a little differently than their single platform counterparts. Individually, each platform has their own norms and customs, filled with M's and V's and Promises, but they aren't alway a good fit to be shared with others. Often they have coupled relationships with the platforms for which they were designed that don't play nicely with others.

Over the past several months I've been migrating the Chicago Roboto app from a Kotlin first Android app to a multiplatform app, and have learned a lot about things that work well for one platform but not another, and how to make those feel a bit more native.

As I share the things I've learned with you, we'll discuss:

• Where to start the multiplatform conversion.
• Adapting native libraries
• Communicating between shared Kotlin code and native platforms
• Designing systems that non-Kotlin developers can get behind.

E86c7de302b490b7f2a67e54960510d0?s=128

Ryan Harter

August 27, 2019
Tweet

Transcript

  1. #DCNYC19 @rharter Effective Multiplatform Architecture #DCNYC19 @rharter Ryan Harter

  2. #DCNYC19 @rharter Multiplatform Auth API Database Login Feature User Repo

    App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  3. #DCNYC19 @rharter Multiplatform Auth API Database Login Feature User Repo

    App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  4. #DCNYC19 @rharter Multiplatform Auth API Database Login Feature User Repo

    App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  5. #DCNYC19 @rharter Multiplatform Auth API Database Login Feature User Repo

    Account Feature Library Feature Social Repo Content Repo Activity API Content API App App App
  6. #DCNYC19 @rharter Multiplatform Auth API Database Login Feature User Repo

    Account Feature Library Feature Social Repo Content Repo Activity API Content API App App App
  7. #DCNYC19 @rharter Multiplatform App App Auth API Database Login Feature

    User Repo Account Feature Library Feature Social Repo Content Repo Activity API Content API
  8. #DCNYC19 @rharter

  9. #DCNYC19 @rharter Getting to Multiplatform #DCNYC19 @rharter Ryan Harter

  10. #DCNYC19 @rharter Step 0 - Modularize

  11. #DCNYC19 @rharter Modularize • Easier to migrate one module at

    a time •
  12. #DCNYC19 @rharter Modularize • Easier to migrate one module at

    a time • “clean” architecture is important (MVI) •
  13. #DCNYC19 @rharter Modularize • Easier to migrate one module at

    a time • “clean” architecture is important (MVI) • Inversion of Control (Dependency Injection) •
  14. #DCNYC19 @rharter Modularize • Easier to migrate one module at

    a time • “clean” architecture is important (MVI) • Inversion of Control (Dependency Injection) • Minimal platform dependencies •
  15. #DCNYC19 @rharter Modularize • Easier to migrate one module at

    a time • “clean” architecture is important (MVI) • Inversion of Control (Dependency Injection) • Minimal platform dependencies • Limit to View and Repo dependencies •
  16. #DCNYC19 @rharter Modularize • Easier to migrate one module at

    a time • “clean” architecture is important (MVI) • Inversion of Control (Dependency Injection) • Minimal platform dependencies • Limit to View and Repo dependencies • LiveData
  17. #DCNYC19 @rharter Modularize • Easier to migrate one module at

    a time • “clean” architecture is important (MVI) • Inversion of Control (Dependency Injection) • Minimal platform dependencies • Limit to View and Repo dependencies • LiveData
  18. #DCNYC19 @rharter Modularize Auth API Database Login Feature User Repo

    App
  19. #DCNYC19 @rharter Login Feature Auth API User Repo Modularize Database

    App
  20. #DCNYC19 @rharter Modularize Auth API Database Login Feature User Repo

    App
  21. #DCNYC19 @rharter Modularize Auth API Database Login Feature User Repo

    App
  22. #DCNYC19 @rharter Modularize Auth API Database Login Feature User Repo

    App
  23. #DCNYC19 @rharter Modularize Auth API Database Login Feature User Repo

    App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  24. #DCNYC19 @rharter Multiplatform

  25. #DCNYC19 @rharter Multiplatform Auth API Database Login Feature User Repo

    App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  26. #DCNYC19 @rharter Multiplatform Auth API Database Login Feature User Repo

    Account Feature Library Feature Social Repo Content Repo Activity API Content API App Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  27. #DCNYC19 @rharter Multiplatform Auth API Database Login Feature User Repo

    App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo Account Feature Library Feature Social Repo Content Repo Activity API Content API App
  28. #DCNYC19 @rharter Multiplatform Auth API Database Login Feature User Repo

    App Account Feature Library Feature Social Repo Content Repo Activity API Content API Multiple Similar Apps Single App Multiple Different Apps App Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  29. #DCNYC19 @rharter Single App Auth API Database Login Feature User

    Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  30. #DCNYC19 @rharter Single App Auth API Database Login Feature User

    Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API • All functionality needs to be replicated • Can start anywhere • Same approach as new app
  31. #DCNYC19 @rharter Single App Auth API Database Login Feature User

    Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  32. #DCNYC19 @rharter Single App Auth API Database Login Feature User

    Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  33. #DCNYC19 @rharter Single App Auth API Database Login Feature User

    Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API App
  34. #DCNYC19 @rharter Single App Auth API Database Login Feature User

    Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API App
  35. #DCNYC19 @rharter Single App Auth API Database Login Feature User

    Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API App
  36. #DCNYC19 @rharter Multiplatform Auth API Database Login Feature User Repo

    App Account Feature Library Feature Social Repo Content Repo Activity API Content API Multiple Similar Apps Single App Multiple Different Apps Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API App Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API App Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  37. #DCNYC19 @rharter Multiple Different Apps • Similar to modularization strategy

    • Convert to MPP as you modularize • Pick a feature to convert • Start from the bottom App Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  38. #DCNYC19 @rharter Multiple Different Apps App Auth API Database Login

    Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  39. #DCNYC19 @rharter Multiple Different Apps App Auth API Database Login

    Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  40. #DCNYC19 @rharter Multiple Different Apps App Auth API Database Login

    Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  41. #DCNYC19 @rharter Multiple Different Apps App Auth API Database Login

    Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  42. #DCNYC19 @rharter Multiple Different Apps App Auth API Database Login

    Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  43. #DCNYC19 @rharter Multiple Different Apps App Auth API Database Login

    Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  44. #DCNYC19 @rharter Multiple Different Apps App Auth API Database Login

    Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  45. #DCNYC19 @rharter Multiple Different Apps App Auth API Database Login

    Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  46. #DCNYC19 @rharter Multiple Different Apps App Auth API Database Login

    Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  47. #DCNYC19 @rharter Auth API Database Login Feature User Repo App

    Account Feature Library Feature Social Repo Content Repo Activity API Content API App Multiple Different Apps
  48. #DCNYC19 @rharter Multiplatform Auth API Database Login Feature User Repo

    App Account Feature Library Feature Social Repo Content Repo Activity API Content API Multiple Similar Apps Single App Multiple Different Apps App Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  49. #DCNYC19 @rharter Multiple Similar Apps • Multiple Approaches • New

    Feature • Vertical Migration • Horizontal Migration • Choice depends on existing arch, teams, etc. • Can be done with many small PRs (i.e. reduce risk) Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  50. #DCNYC19 @rharter Auth API Database Login Feature User Repo App

    Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API App Similar Apps - New Features
  51. #DCNYC19 @rharter Database Login Feature User Repo App Account Feature

    Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Similar Apps - New Features Subscription Feature
  52. #DCNYC19 @rharter Database Login Feature User Repo App Account Feature

    Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Similar Apps - New Features Subscription Feature
  53. #DCNYC19 @rharter Database Login Feature User Repo App Account Feature

    Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Similar Apps - New Features Subscription Feature
  54. #DCNYC19 @rharter Subscription Feature Common expect interface UserRepository { suspend

    fun getUser(): User suspend fun updateUser(user: User): User ... }
  55. #DCNYC19 @rharter Subscription Feature Common expect interface UserRepository { suspend

    fun getUser(): User suspend fun updateUser(user: User): User ... }
  56. #DCNYC19 @rharter Subscription Feature Common expect interface UserRepository { suspend

    fun getUser(): User suspend fun updateUser(user: User): User ... } iOS actual typealias UserRepository = backend.UserRepository JVM actual typealias UserRepository = com.example.myApp.backend.UserRepository
  57. #DCNYC19 @rharter Database Login Feature User Repo App Account Feature

    Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Similar Apps - New Features Subscription Feature
  58. #DCNYC19 @rharter Auth API Database Login Feature User Repo App

    Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API App Similar Apps - Vertical
  59. #DCNYC19 @rharter Similar Apps - Vertical Database Login Feature User

    Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API
  60. #DCNYC19 @rharter Auth API Database Login Feature User Repo App

    Account Feature Library Feature Social Repo Content Repo Activity API Content API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Similar Apps - Vertical
  61. #DCNYC19 @rharter Database Login Feature User Repo App Account Feature

    Library Feature Social Repo Content Repo Activity API Content API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Similar Apps - Vertical
  62. #DCNYC19 @rharter Database Login Feature User Repo App Account Feature

    Library Feature Social Repo Content Repo Activity API Content API Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Similar Apps - Vertical
  63. #DCNYC19 @rharter Login Feature User Repo App Account Feature Library

    Feature Social Repo Content Repo Activity API Content API Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Similar Apps - Vertical
  64. #DCNYC19 @rharter User Repo Login Feature App Account Feature Library

    Feature Social Repo Content Repo Activity API Content API Login Feature App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database User Repo Similar Apps - Vertical
  65. #DCNYC19 @rharter Login Feature App Account Feature Library Feature Social

    Repo Content Repo Activity API Content API Login Feature App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database User Repo Similar Apps - Vertical
  66. #DCNYC19 @rharter Login Feature App Account Feature Library Feature Social

    Repo Content Repo Activity API Content API App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database User Repo Login Feature Similar Apps - Vertical
  67. #DCNYC19 @rharter Database Login Feature User Repo App Account Feature

    Library Feature Social Repo Content Repo Activity API Content API Auth API App Similar Apps - Vertical
  68. #DCNYC19 @rharter Auth API Database Login Feature User Repo Account

    Feature Library Feature Social Repo Content Repo Activity API Content API App Auth API Database Login Feature User Repo Account Feature Library Feature Social Repo Content Repo Activity API Content API App Similar Apps - Horizontal
  69. #DCNYC19 @rharter Database Login Feature User Repo Account Feature Library

    Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API App Similar Apps - Horizontal
  70. #DCNYC19 @rharter Database Login Feature User Repo Account Feature Library

    Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API App Similar Apps - Horizontal
  71. #DCNYC19 @rharter Database User Repo Account Feature Library Feature Social

    Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API App Similar Apps - Horizontal
  72. #DCNYC19 @rharter Database User Repo Account Feature Library Feature Social

    Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Library Feature Social Repo Content Repo Activity API Content API Auth API App Similar Apps - Horizontal Account Feature Account Feature Library Feature
  73. #DCNYC19 @rharter Database User Repo Social Repo Content Repo Activity

    API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API App Similar Apps - Horizontal User Repo Social Repo Content Repo
  74. #DCNYC19 @rharter Login Feature User Repo App Account Feature Library

    Feature Social Repo Content Repo App Similar Apps - Horizontal Database Activity API Content API Auth API Database Activity API Content API Auth API Auth API Database Activity API Content API
  75. #DCNYC19 @rharter Database User Repo Account Feature Library Feature Social

    Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API App Similar Apps - Horizontal
  76. #DCNYC19 @rharter Login Feature Feature Layer • Interface with platform

    implementations • Views • Repositories (or Use Cases) • Connected at both front and back • How to observe values?
  77. #DCNYC19 @rharter Login Feature Feature Layer To Repositories

  78. #DCNYC19 @rharter Login Feature Feature Layer To Repositories To View

  79. #DCNYC19 @rharter Login Feature Feature Layer To Repositories To View

  80. #DCNYC19 @rharter Login Feature Feature Layer To Repositories To View

    ? ? ? ? ?
  81. #DCNYC19 @rharter Login Feature Feature Layer To Repositories To View

    ? ? ✆ ✆ ✆
  82. #DCNYC19 @rharter Login Feature Feature Layer To Repositories To View

    ? ? ☵ !☵ !☵
  83. #DCNYC19 @rharter Login Feature Feature Layer To Repositories To View

    ? ☵ !☵ !☵ ViewActions
  84. #DCNYC19 @rharter Login Feature Feature Layer To Repositories To View

    ☵ !☵ !☵ ViewActions ViewState
  85. #DCNYC19 @rharter Login Feature Feature Layer To Repositories To View

    ☵ !☵ !☵ ViewActions ViewState ☵
  86. #DCNYC19 @rharter Login Feature Feature Layer To Repositories To View

    ☵ !☵ !☵ ViewActions ViewState
  87. #DCNYC19 @rharter Login Feature Feature Layer To Repositories To View

    ☵ !☵ !☵ ViewActions ViewState !⚛
  88. #DCNYC19 @rharter ⚛ Common package org.reactivestreams.mpp expect interface Subscriber<T> {

    fun onSubscribe(s: Subscription) fun onNext(t: T) fun onError(t: Throwable) fun onComplete() }
  89. #DCNYC19 @rharter ⚛ Common JVM package org.reactivestreams.mpp actual typealias Subscriber<T>

    = org.reactivestreams.Subscriber<T> package org.reactivestreams.mpp expect interface Subscriber<T> { fun onSubscribe(s: Subscription) fun onNext(t: T) fun onError(t: Throwable) fun onComplete() }
  90. #DCNYC19 @rharter ⚛ package org.reactivestreams.mpp actual interface Subscriber<T> { actual

    fun onSubscribe(s: Subscription) actual fun onNext(t: T) actual fun onError(t: Throwable) actual fun onComplete() } Common JVM iOS package org.reactivestreams.mpp actual typealias Subscriber<T> = org.reactivestreams.Subscriber<T> package org.reactivestreams.mpp expect interface Subscriber<T> { fun onSubscribe(s: Subscription) fun onNext(t: T) fun onError(t: Throwable) fun onComplete() }
  91. #DCNYC19 @rharter ⚛ package org.reactivestreams.mpp actual interface Subscriber<T> { actual

    fun onSubscribe(s: Subscription) actual fun onNext(t: T) actual fun onError(t: Throwable) actual fun onComplete() } class BlockSubscriber<T>( private val onNextBlock: (T) -> Unit, private val onErrorBlock: (Throwable) -> Unit, private val onCompleteBlock: () -> Unit ) : Subscriber<T>, Disposable { ... } Common JVM iOS package org.reactivestreams.mpp actual typealias Subscriber<T> = org.reactivestreams.Subscriber<T> package org.reactivestreams.mpp expect interface Subscriber<T> { fun onSubscribe(s: Subscription) fun onNext(t: T) fun onError(t: Throwable) fun onComplete() }
  92. #DCNYC19 @rharter ⚛ package org.reactivestreams.mpp actual interface Subscriber<T> { actual

    fun onSubscribe(s: Subscription) actual fun onNext(t: T) actual fun onError(t: Throwable) actual fun onComplete() } class BlockSubscriber<T>( private val onNextBlock: (T) -> Unit, private val onErrorBlock: (Throwable) -> Unit, private val onCompleteBlock: () -> Unit ) : Subscriber<T>, Disposable { ... } iOS extension Reactive_streams_mppPublisher { func subscribe<T: AnyObject>( onNext onNextBlock: @escaping (T) -> Void, onError onErrorBlock: @escaping (Error) -> Void, onComplete onCompleteBlock: @escaping () -> Void ) -> Disposable { let subscriber = BlockSubscriber<T>( onNextBlock: onNextBlock, onErrorBlock: onErrorBlock, onCompleteBlock: onCompleteBlock ) subscribe(s: subscriber) return subscriber } } iOS - Swift
  93. #DCNYC19 @rharter Login Feature Feature Layer To Repositories To View

    ☵ !☵ !☵ ViewActions ViewState !⚛
  94. #DCNYC19 @rharter Login Feature ViewModel

  95. #DCNYC19 @rharter Login Feature ViewModel Common package com.chicagoroboto.features.shared expect interface

    ViewModel<ViewState : Any> { val viewState: Flow<ViewState> }
  96. #DCNYC19 @rharter Login Feature JVM ViewModel Common package com.chicagoroboto.features.shared expect

    interface ViewModel<ViewState : Any> { val viewState: Flow<ViewState> } package com.chicagoroboto.features.shared actual interface ViewModel<ViewState : Any> { actual val viewState: Flow<ViewState> }
  97. #DCNYC19 @rharter Login Feature Common JVM package com.chicagoroboto.features.shared expect interface

    ViewModel<ViewState : Any> { val viewState: Flow<ViewState> } ViewModel package com.chicagoroboto.features.shared actual interface ViewModel<ViewState : Any> { actual val viewState: Flow<ViewState> } iOS package com.chicagoroboto.features.shared actual interface ViewModel<ViewState : Any> { actual val viewState: Flow<ViewState> fun viewState(): Publisher<ViewState> = viewState.asPublisher() } fun viewState(): Publisher<ViewState> = viewState.asPublisher()
  98. #DCNYC19 @rharter Login Feature ViewModel Common JVM package com.chicagoroboto.features.shared expect

    interface ViewModel<ViewState : Any> { val viewState: Flow<ViewState> } package com.chicagoroboto.features.shared actual interface ViewModel<ViewState : Any> { actual val viewState: Flow<ViewState> } iOS package com.chicagoroboto.features.shared actual interface ViewModel<ViewState : Any> { actual val viewState: Flow<ViewState> fun viewState(): Publisher<ViewState> = viewState.asPublisher() } fun viewState(): Publisher<ViewState> = viewState.asPublisher()
  99. #DCNYC19 @rharter Login Feature SessionListViewModel class SessionListViewModel( private val sessionRepo:

    SessionRepository, speakerRepo SpeakerRepository, favoriteRepo: FavoriteRepository ) : ViewModel<SessionListViewState> { private val dateChannel = ConflatedBroadcastChannel<String>() private val sessionFlow: Flow<List<Session>> = dateChannel.asFlow() .flatMapConcat { sessionRepo.sessionsForDate(it) } private val speakerFlow: Flow<List<Speaker>> = speakerRepo.getSpeakers() private val favoriteFlow: Flow<Set<String>> = favoriteRepo.getFavorites() override val viewState = combine(sessionFlow, speakerFlow, favoriteFlow) { sessions, speakers, favorites -> SessionListViewState(date, viewSessions) } }
  100. #DCNYC19 @rharter Login Feature SessionListViewModel override val viewState = combine(sessionFlow,

    speakerFlow, favoriteFlow) { sessions, speakers, favorites -> SessionListViewState(date, viewSessions) } class SessionListViewModel( private val sessionRepo: SessionRepository, speakerRepo SpeakerRepository, favoriteRepo: FavoriteRepository ) : ViewModel<SessionListViewState> { private val dateChannel = ConflatedBroadcastChannel<String>() private val sessionFlow: Flow<List<Session>> = dateChannel.asFlow() .flatMapConcat { sessionRepo.sessionsForDate(it) } private val speakerFlow: Flow<List<Speaker>> = speakerRepo.getSpeakers() private val favoriteFlow: Flow<Set<String>> = favoriteRepo.getFavorites() override val viewState = combine(sessionFlow, speakerFlow, favoriteFlow) { sessions, speakers, favorites -> SessionListViewState(date, viewSessions) } }
  101. #DCNYC19 @rharter iOS App .subscribe( onNext: { [weak self] (state:

    SessionListViewState) in self?.sessions = state.sessions }, onError: { error in NSLog("Failed to load state.", error) }, onComplete: { NSLog("onComplete") } ) class SessionListViewController: UICollectionViewController { override func viewDidLoad() { super.viewDidLoad() disposables <= self.viewModel.viewState() .subscribe( onNext: { [weak self] (state: SessionListViewState) in self?.sessions = state.sessions }, onError: { error in NSLog("Failed to load state.", error) }, onComplete: { NSLog("onComplete") } ) self.viewModel.setDate(date: self.date) } }
  102. #DCNYC19 @rharter iOS App .subscribe( onNext: { [weak self] (state:

    SessionListViewState) in self?.sessions = state.sessions }, onError: { error in NSLog("Failed to load state.", error) }, onComplete: { NSLog("onComplete") } ) class SessionListViewController: UICollectionViewController { override func viewDidLoad() { super.viewDidLoad() disposables <= self.viewModel.viewState() .subscribe( onNext: { [weak self] (state: SessionListViewState) in self?.sessions = state.sessions }, onError: { error in NSLog("Failed to load state.", error) }, onComplete: { NSLog("onComplete") } ) self.viewModel.setDate(date: self.date) } }
  103. #DCNYC19 @rharter Login Feature Common JVM package com.chicagoroboto.features.shared expect interface

    ViewModel<ViewState : Any> { val viewState: Flow<ViewState> } ViewModel package com.chicagoroboto.features.shared actual interface ViewModel<ViewState : Any> { actual val viewState: Flow<ViewState> } iOS package com.chicagoroboto.features.shared actual interface ViewModel<ViewState : Any> { actual val viewState: Flow<ViewState> fun viewState(): Publisher<ViewState> = viewState.asPublisher() } fun viewState(): Publisher<ViewState> = viewState.asPublisher()
  104. #DCNYC19 @rharter Login Feature Feature Layer To Repositories To View

    ☵ !☵ !☵ ViewActions ViewState !⚛
  105. #DCNYC19 @rharter Database User Repo Account Feature Library Feature Social

    Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API App Similar Apps - Horizontal
  106. #DCNYC19 @rharter Login Feature User Repo App Account Feature Library

    Feature Social Repo Content Repo App Similar Apps - Horizontal Auth API Database Activity API Content API
  107. #DCNYC19 @rharter Multiplatform Auth API Database Login Feature User Repo

    App Account Feature Library Feature Social Repo Content Repo Activity API Content API Multiple Similar Apps Single App Multiple Different Apps App Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API Auth API Database Login Feature User Repo App Account Feature Library Feature Social Repo Content Repo Activity API Content API
  108. #DCNYC19 @rharter Effective Multiplatform Architecture #DCNYC19 @rharter Ryan Harter