Fundamentals #10 - Architecture & Tying things up

3142db3adb711e247e371153b5777e04?s=47 Britt Barak
January 08, 2018

Fundamentals #10 - Architecture & Tying things up

Closing talk on Android fundamentals course: architecture design patterns and suggested implementation, with new Android Architecture Components.

3142db3adb711e247e371153b5777e04?s=128

Britt Barak

January 08, 2018
Tweet

Transcript

  1. Architecture & Tying things up Fundamentals #10 8/1/2018 Britt Barak

  2. One thing is sure Everything will change. Quick.

  3. Our Goals - Write quicker - Change easily - Easy

    for others to understand
  4. Our Goals - Write quicker - Change easily - Easy

    for others to understand - Rely on the code (testable) - Robust - Scalable
  5. Who loves Jelly Beans?

  6. None
  7. None
  8. None
  9. None
  10. Where to start?

  11. None
  12. Clean Architecture https://8thlight.com/blog/uncle-bob/2012 /08/13/the-clean-architecture.html

  13. Presentation Layer Data Layer Domain Layer

  14. Presentation Layer

  15. class JellyBeanViewModel extends ViewModel { String flavor; int r; int

    g; int b; boolean isLoading;
  16. Data Layer

  17. class JellyBeanViewModel String flavor; int r; int g; int b;

    boolean isLoading; class JellyBean String flavor; String color;
  18. Presentation Data ViewModel DataModel ?

  19. Presentation Data Domain DataModel Interactor ViewModel

  20. Domain Layer

  21. Presentation Layer Data Layer Domain Layer

  22. Communication: Architecture patterns

  23. None
  24. MVC Model View Controller

  25. Presentation Domain View Controller User Input Data DataModel

  26. MVP Model View Presenter

  27. Presentation Domain View Presenter User Input ViewModel

  28. Presentation Domain View Presenter User Input ViewModel SAVE Data DataModel

  29. What if I change the UI? (also, is this unit

    testiable?)
  30. Presentation Domain View Presenter User Input ViewModel

  31. Presentation Domain View Presenter User Input IView ViewModel IPresenter

  32. Questions?

  33. What can the Presenter do?

  34. What if we POST instead of PM?

  35. Presentation Domain View Presenter User Input IView ViewModel IPresenter ViewModel

    I Changed
  36. Presenter doesn’t know View No contract needed

  37. Presentation Domain View Presenter User Input IView ViewModel IPresenter ViewModel

    I Changed
  38. Presentation Domain View Presenter User Input ViewModel

  39. Presentation Domain View ViewModel User Input

  40. MVVM Model View ViewModel

  41. Questions?

  42. This are Patterns & Concepts - Many variants - Which

    should you use? - Are there others?
  43. MVI - Model View Intent http://hannesdorfmann.com/android/mosby3-mvi-1 https://github.com/sockeqwe/mosby https://github.com/Arello-Mobile/Moxy

  44. None
  45. Let’s Play

  46. None
  47. class JellyBeanViewModel extends ViewModel { String flavor; int r; int

    g; int b;
  48. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_add_bean); setViewModel() setUi();

    }
  49. void setViewModel(){ this.viewModel = new JellyBeanViewModel(); }

  50. UI represents the ViewModel state

  51. Presentation Domain Layer UseCase View ViewModel User Input

  52. 1. Update the viewModel

  53. public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { switch

    (seekBar.getId()) { case R.id.sb_r: viewModel.setR(progress); break; //...
  54. 2. View Model notifies

  55. - Data binding - RxJava (/RxAndroid) - Event Bus -

    LiveData How to notify?
  56. LiveData - Observable data holder class - Lifecycle-aware - Updates

    only on started / resumed state - Removes itself on destroyed state - No memory leaks https://developer.android.com/topic/libraries/architecture/livedata.html
  57. public class JellyBeanViewModel extends ViewModel { String flavor; LiveData<Integer> r;

    LiveData<Integer> g; LiveData<Integer> b;
  58. public class JellyBeanViewModel extends ViewModel { LiveData<Integer> r; public void

    setR(int newR) { newR = validate(newR); r.setValue(newR); }
  59. 3. Create an observer

  60. Observer<Integer> colorChangedObserver = (Integer integer) -> { beanIv.setColorFilter(viewModel.getColor()); };

  61. 4. Observe ViewModel changes

  62. viewModel.getR() .observe(this, colorChangedObserver); Observer is tied to this lifecycle, and

    will be removed as the lifecycle ends. LiveData
  63. Presentation Domain Layer UseCase View ViewModel User Input

  64. Questions?

  65. Persisting ViewModel

  66. None
  67. setViewModel() -> { this.viewModel = ViewModelProviders.of(this) .get(JellyBeanViewModel.class); }

  68. Save The Jelly Bean!

  69. Data Layer

  70. - Data Model - Repository Data Layer

  71. class JellyBeanViewModel String flavor; int r; int g; int b;

    class JellyBean String flavor; String color;
  72. - One per data type (e.g jelly bean, recipe, user….).

    - Encapsulates the logic of getting/setting the data. - CRUD operations (Create, Read, Update, Delete) Repository
  73. class JellyBeanRepo{ }

  74. class JellyBeanRepo{ LiveData<JellyBean> getJellyBean(String id){ }

  75. LiveData<JellyBean> getJellyBean(String id) { return myFirebaseClient.getJellyBean(id) }

  76. LiveData<JellyBean> getJellyBean(String id) { if (cache.hasJellyBean(id)){ return cache.getJellyBean(id); } else{

    return myFirebaseClient.getJellyBean(id) } }
  77. LiveData<JellyBean> getJellyBean(String id) { if (cache.hasJellyBean(id)){ return cache.getJellyBean(id); } else

    if (appDatabase.hasJellyBean(id)) { return appDatabase.jellyBeanDao().getJellyBean(id); } else{ return myFirebaseClient.getJellyBean(id) }
  78. LiveData<JellyBean> getJellyBean(String id) { if (cache.hasJellyBean(id)){ return cache.getJellyBean(id); } else

    if (appDatabase.hasJellyBean(id)) { return appDatabase.jellyBeanDao().getJellyBean(id); } else{ return myApiClient.getJellyBean(id) }
  79. Presentation Layer Data Layer ViewModel DataModel ?

  80. Presentation Layer Data Layer Domain Layer DataModel Interactor ViewModel

  81. Domain Layer

  82. 1. Create Use Case

  83. class SaveJellyBean extends UseCase { void execute() { }

  84. 2. Convert Models

  85. public class SaveJellyBean extends UseCase { public void execute(JellyBeanViewModel viewModel)

    { JellyBean data = prepareDataModel(viewModel); }
  86. JellyBean prepareDataModel(JellyBeanViewModel viewModel){ String beanColorString = String.format("#%06X", (0xFFFFFF & viewModel.getColor()));

    JellyBean data = new JellyBean(viewModel.getFlavor(), beanColorString); return data; }
  87. 3. Call Repository

  88. public class SaveJellyBean extends UseCase { public void execute(JellyBeanViewModel viewModel)

    { JellyBean data = prepareDataModel(viewModel); repo.saveBean(data); }
  89. 4. Execute

  90. Presentation Layer Data Layer Domain Layer SaveJellyBean .execute() JellyBeanRepo .save()

  91. Questions?

  92. Reusing interactors - Edit Jelly Bean screen - Different UI

    - Same SaveJellyBean use case
  93. Another word about Repository...

  94. Data Network Service AppDatabase Cache? Domain Some Usecase Repository

  95. Thank You ! goo.gl/p96gpF Read more:

  96. VOTE HERE: https://goo.gl/tsmeK2

  97. Code lab

  98. Exercise 1. Android lifecycle-aware components goo.gl/92wWf3 2. For Sum Up:

    Build an App with Architecture Components goo.gl/5og51s