view state machine for network calls on android
play

VIEW STATE MACHINE FOR NETWORK CALLS ON ANDROID @MANDYBESS - PowerPoint PPT Presentation

VIEW STATE MACHINE FOR NETWORK CALLS ON ANDROID @MANDYBESS THOUGHTBOT WHAT IS A VIEW STATE MACHINE? ! BUILD AN APP TOGETHER ! " GAME OF CONES ! MODELING !"! ICE CREAM - title - icon data class IceCream(val title: String, val


  1. VIEW STATE MACHINE FOR NETWORK CALLS ON ANDROID @MANDYBESS

  2. THOUGHTBOT

  3. WHAT IS A VIEW STATE MACHINE?

  4. !

  5. BUILD AN APP TOGETHER ! "

  6. GAME OF CONES !

  7. MODELING !"!

  8. ICE CREAM - title - icon

  9. data class IceCream(val title: String, val iconUrl: String)

  10. ! ➡ "

  11. MVP MODEL VIEW PRESENTER

  12. VIEW INTERFACE interface MainView { fun showTitle(title: String) fun showIcon(url: String) }

  13. PRESENTER class MainPresenter(val view: MainView) { fun onCreate() { val iceCream = ?? view.showTitle(iceCream.title) view.showIcon(iceCream.iconUrl) } }

  14. DATA STORE interface DataStore { fun fetchCone(): IceCream }

  15. PRESENTER + DATA STORE + class MainPresenter(val view: MainView, val dataStore: DataStore) { fun onCreate() { + val iceCream = dataStore.fetchCone() view.showTitle(iceCream.title) view.showIcon(iceCream.iconUrl) } }

  16. TESTING !

  17. PRESENTER TEST class MainPresenterTest { val view = mock<MainView>() val dataStore = mock<DataStore>() val fakeIceCream = IceCream("Vanilla", "www.icecream.com") @Test fun test_onCreate() { //stub response whenever(dataStore.fetchCone()).thenReturn(fakeIceCream) val presenter = MainPresenter(view, dataStore) presenter.onCreate() verify(view).showTitle("Vanilla") verify(view).showIcon("www.icecream.com") verifyNoMoreInteractions(view) }

  18. PRESENTER TEST class MainPresenterTest { val view = mock<MainView>() val dataStore = mock<DataStore>() val fakeIceCream = IceCream("Vanilla", "www.icecream.com") @Test fun test_onCreate() { //stub response whenever(dataStore.fetchCone()).thenReturn(fakeIceCream) val presenter = MainPresenter(view, dataStore) presenter.onCreate() verify(view).showTitle("Vanilla") verify(view).showIcon("www.icecream.com") verifyNoMoreInteractions(view) }

  19. PRESENTER TEST class MainPresenterTest { val view = mock<MainView>() val dataStore = mock<DataStore>() val fakeIceCream = IceCream("Vanilla", "www.icecream.com") @Test fun test_onCreate() { //stub response whenever(dataStore.fetchCone()).thenReturn(fakeIceCream) val presenter = MainPresenter(view, dataStore) presenter.onCreate() verify(view).showTitle("Vanilla") verify(view).showIcon("www.icecream.com") verifyNoMoreInteractions(view) }

  20. PRESENTER TEST class MainPresenterTest { val view = mock<MainView>() val dataStore = mock<DataStore>() val fakeIceCream = IceCream("Vanilla", "www.icecream.com") @Test fun test_onCreate() { //stub response whenever(dataStore.fetchCone()).thenReturn(fakeIceCream) val presenter = MainPresenter(view, dataStore) presenter.onCreate() verify(view).showTitle("Vanilla") verify(view).showIcon("www.icecream.com") verifyNoMoreInteractions(view) }

  21. PRESENTER TEST class MainPresenterTest { val view = mock<MainView>() val dataStore = mock<DataStore>() val fakeIceCream = IceCream("Vanilla", "www.icecream.com") @Test fun test_onCreate() { //stub response whenever(dataStore.fetchCone()).thenReturn(fakeIceCream) val presenter = MainPresenter(view, dataStore) presenter.onCreate() verify(view).showTitle("Vanilla") verify(view).showIcon("www.icecream.com") verifyNoMoreInteractions(view) }

  22. PRESENTER TEST class MainPresenterTest { val view = mock<MainView>() val dataStore = mock<DataStore>() val fakeIceCream = IceCream("Vanilla", "www.icecream.com") @Test fun test_onCreate() { //stub response whenever(dataStore.fetchCone()).thenReturn(fakeIceCream) val presenter = MainPresenter(view, dataStore) presenter.onCreate() verify(view).showTitle("Vanilla") verify(view).showIcon("www.icecream.com") verifyNoMoreInteractions(view) }

  23. PRESENTER TEST class MainPresenterTest { val view = mock<MainView>() val dataStore = mock<DataStore>() val fakeIceCream = IceCream("Vanilla", "www.icecream.com") @Test fun test_onCreate() { //stub response whenever(dataStore.fetchCone()).thenReturn(fakeIceCream) val presenter = MainPresenter(view, dataStore) presenter.onCreate() verify(view).showTitle("Vanilla") verify(view).showIcon("www.icecream.com") verifyNoMoreInteractions(view) }

  24. NETWORK CALLS !"

  25. DATA STORE + RX interface DataStore { + fun fetchCone(): Observable<IceCream> }

  26. PRESENTER + RX class MainPresenter(val view: MainView, val dataStore: DataStore) { fun onCreate() { dataStore.fetchCone() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { iceCream -> // on success view.showTitle(iceCream.title) view.showIcon(iceCream.iconUrl) }, { error -> // on error } ) } }

  27. PRESENTER + RX class MainPresenter(val view: MainView, val dataStore: DataStore) { fun onCreate() { dataStore.fetchCone() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { iceCream -> // on success view.showTitle(iceCream.title) view.showIcon(iceCream.iconUrl) }, { error -> // on error } ) } }

  28. PRESENTER + RX class MainPresenter(val view: MainView, val dataStore: DataStore) { fun onCreate() { dataStore.fetchCone() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { iceCream -> // on success view.showTitle(iceCream.title) view.showIcon(iceCream.iconUrl) }, { error -> // on error } ) } }

  29. PRESENTER + RX class MainPresenter(val view: MainView, val dataStore: DataStore) { fun onCreate() { dataStore.fetchCone() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { iceCream -> // on success view.showTitle(iceCream.title) view.showIcon(iceCream.iconUrl) }, { error -> // on error } ) } }

  30. PRESENTER + RX class MainPresenter(val view: MainView, val dataStore: DataStore) { fun onCreate() { // loading?? dataStore.fetchCone() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { iceCream -> // on success view.showTitle(iceCream.title) view.showIcon(iceCream.iconUrl) }, { error -> // on error } ) } }

  31. VIEW INTERFACE + NETWORKING interface MainView { fun showTitle(title: String) fun showIcon(url: String) + fun showLoading() + fun hideLoading() + fun showError(errorMessage: String) }

  32. PRESENTER + NETWORKING class MainPresenter(val view: MainView, val dataStore: DataStore) { fun onCreate() { + view.showLoading() dataStore.fetchCone() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { iceCream -> + view.hideLoading() view.showTitle(iceCream.title) view.showIcon(iceCream.iconUrl) }, { error -> + view.hideLoading() + view.showError(error.message) } ) } }

  33. PRESENTER TEST + RX + NETWORKING ... @Test fun test_onCreate_success() { // stub response - whenever(dataStore.fetchCone()).thenReturn(fakeIceCream) + whenever(dataStore.fetchCone()).thenReturn(Observable.just(fakeIceCream)) val presenter = MainPresenter(view, dataStore) presenter.onCreate() + verify(view).showLoading() + verify(view).hideLoading() verify(view).showTitle("Vanilla") verify(view).showIcon("www.icecream.com") verifyNoMoreInteractions(view) }

  34. PRESENTER TEST + RX + NETWORKING ... @Test fun test_onCreate_error() { // stub response val errorMessage = "There was an error" whenever(dataStore.fetchCone()).thenReturn(Observable.error(Throwable(errorMessage))) val presenter = MainPresenter(view, dataStore) presenter.onCreate() verify(view).showLoading() verify(view).hideLoading() verify(view).showError(errorMessage) verifyNoMoreInteractions(view) }

  35. WE DID IT !

  36. !

  37. UPDATES 1. Update our model 2. Update our view interface 3. Update our presenter 4. Update presenter tests

  38. MODEL UPDATE data class IceCream(val title: String, val iconUrl: String, val calorieCount: Int)

  39. VIEW INTERFACE + CALORIES interface MainView { fun showTitle(title: String) fun showIcon(url: String) fun showLoading() fun hideLoading() fun showError(errorMessage: String) + fun showCalorieCount(calorieCount: String) }

  40. PRESENTER + CALORIES class MainPresenter(val view: MainView, val dataStore: DataStore) { fun onCreate() { view.showLoading() dataStore.fetchCone() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { iceCream -> view.hideLoading() view.showTitle(iceCream.title) view.showIcon(iceCream.iconUrl) + view.showCalorieCount(context.getString(R.string.formatted_calorie_count, iceCream.calorieCount)) }, { error -> view.hideLding() view.showError(error.message) } ) } }

Recommend


More recommend