Use MVI Architecture in Kotlin × Android

93dece28ac18d9c0886335e4730ab27b?s=47 itome
November 15, 2018

Use MVI Architecture in Kotlin × Android

93dece28ac18d9c0886335e4730ab27b?s=128

itome

November 15, 2018
Tweet

Transcript

  1.  Koin×AndroidͰMVI ΞʔΩςΫνϟΛ࠾༻͢Δ #potatetips #56

  2. ࣗݾ঺հ 0min

  3. ࣗݾ঺հ 0min ௩ຊ෢ࢤ ! https://twitter.com/itometeam " https://github.com/itome # https://medium.com/@itometeam cyberagent/cats

  4. MVI Architectureͱ͸ʁ 1min

  5. MVI Architectureͱ͸ʁ 1min ୯ํ޲σʔλϑϩʔ • Model • View • Intent(≠android.content.Intent)

    ViewModelͰ Intent → Action → Result → Result ͱσʔλΛม׵͍ͯ͘͜͠ͱͰ ঢ়ଶΛมߋ͢Δ
  6. RxʹΑΔ࣮૷ྫ 2min

  7. RxʹΑΔ࣮૷ྫ 2min sealed class EventsIntent : MviIntent { object FetchFirstPageIntent

    : EventsIntent() data class FetchPageIntent(val pageNum: Int) : EventsIntent() object FetchLoginUserIntent : EventsIntent() } sealed class EventsAction : MviAction { object FetchFirstPageAction : EventsAction() data class FetchEventsPageAction( val pageNum: Int ) : EventsAction() object FetchLoginUserAction : EventsAction() }
  8. RxʹΑΔ࣮૷ྫ 2min private fun actionFromIntent(intent: EventsIntent): EventsAction { return when

    (intent) { FetchFirstPageIntent -> FetchFirstPageAction is FetchPageIntent -> FetchEventsPageAction(intent.pageNum) FetchLoginUserIntent -> FetchLoginUserAction } }
  9. RxʹΑΔ࣮૷ྫ 2min sealed class EventsResult : MviResult { sealed class

    FetchFirstPageResult : EventsResult() { data class Success(val events: List<Event>) : FetchFirstPageResult() data class Failure(val error: Throwable) : FetchFirstPageResult() object InFlight : FetchFirstPageResult() } sealed class FetchEventsPageResult : EventsResult() { data class Success(val events: List<Event>) : FetchEventsPageResult() data class Failure(val error: Throwable) : FetchEventsPageResult() object InFlight : FetchEventsPageResult() } sealed class FetchLoginUserResult : EventsResult() { data class Success(val user: User) : FetchLoginUserResult() data class Failure(val error: Throwable) : FetchLoginUserResult() object InFlight : FetchLoginUserResult() } }
  10. RxʹΑΔ࣮૷ྫ 2min override val actionProcessor = mergeProcessor( fetchFirstPageProcessor to FetchFirstPageAction::class,

    fetchEventsPageProcessor to FetchEventsPageAction::class, fetchLoginUserProcessor to FetchLoginUserAction::class ) private val fetchFirstPageProcessor = createProcessor<FetchFirstPageAction, FetchFirstPageResult> { repository.getEvents(1) .toObservable() .map { user -> FetchFirstPageResult.Success(user) } .cast(FetchFirstPageResult::class.java) .onErrorReturn(FetchFirstPageResult::Failure) .subscribeOn(schedulerProvider.io()) .observeOn(schedulerProvider.ui()) .startWith(FetchFirstPageResult.InFlight) }
  11. RxʹΑΔ࣮૷ྫ 2min data class EventsViewState( val loginUser: User?, val events:

    List<Event>, val error: Throwable?, val nextPage: Int, val isLoading: Boolean ) : MviViewState { companion object { fun idle(): EventsViewState { return EventsViewState( loginUser = null, events = emptyList(), error = null, nextPage = 1, isLoading = false ) } } }
  12. RxʹΑΔ࣮૷ྫ 2min private val reducer = { previousState: EventsViewState, result:

    EventsResult -> when (result) { is FetchFirstPageResult -> when (result) { is FetchFirstPageResult.Success -> previousState.copy( events = result.events, error = null, isLoading = false, nextPage = 2 ) is FetchFirstPageResult.Failure -> previousState.copy(error = result.error, isLoading = false) FetchFirstPageResult.InFlight -> previousState.copy(isLoading = true) }
  13. RxʹΑΔ࣮૷ྫ 2min private fun compose(): Observable<EventsViewState> { return intentsSubject .map(this::actionFromIntent)

    .compose(actionProcessorHolder.actionProcessor) .scan(EventsViewState.idle(), reducer) .replay(1) .autoConnect(0) }
  14. RxʹΑΔ࣮૷ྫ 2min ιʔείʔυ͸ https://github.com/itome/GithubMVI

  15. ϝϦοτ / σϝϦοτ 2min

  16. ϝϦοτ 2min ϓϩάϥϚʔʹର͢Δ੍໿͕ڧ͍ ςετ͕༰қ ɾਓʹΑ࣮ͬͯ૷͕มΘΔ෦෼ΛͰ͖Δ͚ͩ཈͑ΒΕΔ ɾ֤ॲཧͰೖྗͱग़ྗ͕ඞͣ̍ΧॴʹͳΔͨΊɺ ɹςετ͢΂͖͜ͱ͕໌֬ ΤϥʔϋϯυϦϯά͕༰қ ɾViewͷΠϕϯτ͔ΒViewͷߋ৽·Ͱ͕ҰຊͷετϦʔϜʹ ɹͳ͍ͬͯΔͨΊɺྫ֎ॲཧ͕Θ͔Γ΍͍͢

  17. σϝϦοτ 2min ̍ճ͖ΓͷΠϕϯτΛ఻͑Δͷ͕೉͍͠ ෳࡶͳϨΠΞ΢τͰ͸ViewStateͷߋ৽ͷॲཧ͕ॏ͘ͳΔ ɾViewModelͷग़ྗ͕ViewStateͷΈͰ͋ΔͨΊɺҰճ͖ΓͷΠϕϯτΛ ɹViewModelଆ͔Βى͍ͨ࣌͜͠͸ɺflagΛ࣋ͨͤΔͳͲͷ޻෉͕ඞཁ ɾAndroidʹ͸Reactͷࠩ෼ߋ৽ͷΑ͏ͳ࢓૊Έ͕ଘࡏ͠ͳ͍ͨΊɺ ɹViewStateͷҰ෦Λߋ৽͚ͨͩ͠ͰɺViewStateʹؔ࿈͢Δ ɹશͯͷView͕ߋ৽͞Εͯ͠·͏ ৑௕ʹͳΓ΍͍͢

    ɾίʔυͷϘΠϥʔϓϨʔτ͕ଟ͍ͨΊɺখ͞ͳॲཧͰ΋͔ͳΓͷ ɹίʔυΛॻ͘ඞཁ͕͋Δɻ
  18. ·ͱΊ 0.5min

  19. ͋Γ͕ͱ͏͍͟͝·ͨ͠ ! https://twitter.com/itometeam " https://github.com/itome # https://medium.com/@itometeam Takeshi Tsukamoto cyberagent/cats