Slide 1

Slide 1 text

MVVM ARCHITECTURE ON ANDROID Petr Nohejl

Slide 2

Slide 2 text

WHAT IS MVVM? ● Model (data) - View (UI) - ViewModel (state & logic) ● aka Model - View - Binder Source: https://msdn.microsoft.com/en-us/library/gg405484.aspx

Slide 3

Slide 3 text

MODEL ● Represents a data provider ○ REST ○ Database ○ Preferences ○ etc.

Slide 4

Slide 4 text

VIEW ● Represents UI components ● Displaying the data

Slide 5

Slide 5 text

VIEWMODEL ● Represents a display logic ● Prepares the data for presentation ● Uses Observer pattern to notify changes

Slide 6

Slide 6 text

VIEWMODEL ● Represents display logic ● Prepares the data for presentation ● Uses Observer pattern to notify changes ViewModel is... ● Abstraction of the view exposing public properties and commands ● State of the data in the model ● Maintains the state of the view ● Value converter (raw data to presentation-friendly properties)

Slide 7

Slide 7 text

MVVM VS. MVP ● Binding ● One-to-Many relation ● Many Views can be mapped to one ViewModel ● View has a reference to the ViewModel ● ViewModel has no information about the View

Slide 8

Slide 8 text

MOTIVATION

Slide 9

Slide 9 text

MOTIVATION ● Separation of concerns ● Better testability ● Follow SOLID principles Source: http://tiny-giant-books.com/img/Uncle-Bob-Transparent-Background.png

Slide 10

Slide 10 text

HOW TO IMPLEMENT IT?

Slide 11

Slide 11 text

HOW TO IMPLEMENT A BINDER? ● Data Binding Library ● RxJava

Slide 12

Slide 12 text

HOW TO IMPLEMENT LAYERS? ● Model (data provider) ● View (Activity/Fragment/XML) ● ViewModel (plain Java or BaseObservable) SOLID

Slide 13

Slide 13 text

MODEL RESPONSIBILITIES (DATA) ● Retrofit ● SQLite db ● Realm db ● Firebase ● SharedPreferences ● Geolocation ● Broadcasts

Slide 14

Slide 14 text

VIEW RESPONSIBILITIES (UI) ● Working with android.view, android.widget, etc. ● Showing Dialogs, Toasts, Snackbars ● Event listeners ● Starting Activities ● Handling Menu ● Handling permissions ● Other Android specific stuff & methods which require reference to the Activity Context

Slide 15

Slide 15 text

VIEWMODEL RESPONSIBILITIES (STATE & LOGIC) ● Exposing state (progress, offline, empty, error, etc.) ● Exposing data ● Handling visibility ● Handling Extras & Arguments (Bundle) ● Input validation ● Executing data calls in the Model ● Executing UI commands in the View

Slide 16

Slide 16 text

ABSTRACTION ● Command pattern ● Navigator pattern ● Repository pattern ● etc. ABSTRACTION SIMPLICITY

Slide 17

Slide 17 text

DEPENDENCY INJECTION new MyViewModel( Navigator navigator, MyRepository repository, MyPreferences preferences, MyGeolocationService geolocation, MyBroadcastBus broadcast); SOLID

Slide 18

Slide 18 text

WHAT ABOUT ANDROID API? ● ViewModel layer should be separated from Android specific classes ● Permissions, Intents, Menu etc. in Activity/Fragment

Slide 19

Slide 19 text

WHAT ABOUT ANDROID API? ● Separate UI stuff from Android stuff in the View or not? Activity implements View onCreate() onCreateOptionsMenu() onRequestPermissionsResult() showDialog() onItemClick()

Slide 20

Slide 20 text

WHAT ABOUT CONTEXT? ● ViewModel should use only the Application Context Source: https://possiblemobile.com/2013/06/context/

Slide 21

Slide 21 text

EVENT LISTENERS ● Defined in the View ● Decoupled - separate business logic from UI ● Example - 3 screens, loading data on different actions ViewModel loadUsers() onRefreshButtonClick() onDialogPositiveClick() Activity #1 onRefreshButtonClick() Activity #3 viewModel.onGeolocationRespond() Activity #2 onDialogPositiveClick() SOLID

Slide 22

Slide 22 text

@{ EXPRESSIONS } What’s wrong about this?

Slide 23

Slide 23 text

@{ EXPRESSIONS } android:visibility="@{age < 18 ? View.GONE : View.VISIBLE}" What is wrong: ❌ Mixing display logic with UI ❌ Breaking single responsibility (to show data) ❌ Impossible to unit test and hard to debug Better way: ● Views should be as dumb as possible ● Primitive expressions are probably OK

Slide 24

Slide 24 text

TESTING Model and ViewModel ● JUnit & Mockito (unit tests) ● Pure Java without Android API View ● Espresso (UI tests) ● No logic

Slide 25

Slide 25 text

PROS & CONS ✅ Readable code ✅ Maintainable code ✅ Testable code ✅ SOLID code ✅ No god classes ❌ View = Java + XML ❌ Mixed Android API + View

Slide 26

Slide 26 text

EXAMPLE CODE

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

VIEW public interface StockDetailView { void onButtonClick(View view); } public class StockDetailFragment extends BaseFragment implements StockDetailView { private FragmentStockDetailBinding mBinding; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mBinding = FragmentStockDetailBinding. inflate(inflater); mBinding.setView( this); mBinding.setViewModel(getViewModel()); return mBinding.getRoot(); } @Override public void onButtonClick(View view) { getViewModel().loadStock(); } ... }

Slide 29

Slide 29 text

XML LAYOUT

Slide 30

Slide 30 text

VIEWMODEL public class StockDetailViewModel extends BaseViewModel { public final ObservableField state = new ObservableField<>(); public final ObservableField stock = new ObservableField<>(); private DataProvider mDataProvider; // represents model @Override public void onStart() { super.onStart(); if(stock.get() == null) loadStock(); } public void loadStock() { if(NetworkUtility. isOnline(StocksApplication. getContext())) { state.set(StatefulLayout.State. PROGRESS); mDataProvider.loadStock(...); // retrieves data from model and updates stock and state fields } else { state.set(StatefulLayout.State. OFFLINE); } } ... }

Slide 31

Slide 31 text

DEMO PROJECT ● https://github.com/petrnohejl/Android-Stocks ○ MVVM architecture ○ Data binding ○ RecyclerView ○ RxJava ○ Retrolambda ○ OkHttp ○ Retrofit ○ GSON ○ Glide ○ LeakCanary

Slide 32

Slide 32 text

LIBRARIES & EXAMPLES ● https://github.com/inloop/AndroidViewModel ● https://github.com/jakubkinst/Android-ViewModelBinding/ ● https://github.com/fabioCollini/mv2m ● https://github.com/hitherejoe/MVVM_Hacker_News ● https://github.com/ivacf/archi ● https://github.com/erikcaffrey/People-MVVM ● https://github.com/radzio/android-data-binding-recyclerview ● https://github.com/radzio/android-data-binding-command ● https://github.com/Nilzor/mvp-to-mvvm-transition ● https://github.com/googlesamples/android-architecture

Slide 33

Slide 33 text

ARTICLES ● https://medium.com/@artem_zin/m-model-from-mvc-mvp-in-android-flow-and-mortar-bd1e50c45395#.dp51cjddi ● https://medium.com/android-news/android-architecture-2f12e1c7d4db#.eq9u6h3zl ● https://medium.com/ribot-labs/approaching-android-with-mvvm-8ceec02d5442 ● https://medium.com/ribot-labs/android-application-architecture-8b6e34acda65#.okk4mtrc5 ● https://medium.com/mobiwise-blog/android-basic-project-architecture-for-mvp-72f4b33252d0#.ncwed522y ● http://cases.azoft.com/mvvm-android-data-binding/ ● http://blog.stablekernel.com/mvvm-on-android-using-the-data-binding-library/ ● http://tech.vg.no/2015/07/17/android-databinding-goodbye-presenter-hello-viewmodel/ ● http://blog.grio.com/2016/03/building-android-apps-with-mvvm-and-data-binding.html ● https://medium.com/cobe-mobile/architecting-android-with-data-binding-and-mvvm-in-mind-8874bbec0b0d ● http://www.codeprogression.com/2015/10/30/android-presentation-model/ ● https://catinean.com/2015/05/31/how-you-can-go-wrong-with-the-new-data-binding-api/ ● https://corner.squareup.com/2014/10/advocating-against-android-fragments.html ● https://www.bignerdranch.com/blog/shades-of-mvvm/ ● https://medium.com/upday-devs/android-architecture-patterns-part-3-model-view-viewmodel-e7eeee76b73b ● https://medium.com/upday-devs/mvvm-rxjava-learnings-1819423f9592 ● https://medium.com/@Miqubel/refactoring-to-mvvm-40ebafff43de#.yhj3vy8pp ● https://medium.com/@manuelvicnt/rxjava2-android-mvvm-lifecycle-app-structure-with-retrofit-2-cf903849f49e ● https://medium.com/@hiBrianLee/writing-testable-android-mvvm-app-prelude-e49f7e6223

Slide 34

Slide 34 text

TALKS ● https://www.youtube.com/watch?v=0iC2a3mC7Jc ● https://www.youtube.com/watch?v=GKGjI4b7_lA ● https://www.youtube.com/watch?v=5EPbPBarWhI ● https://www.youtube.com/watch?v=JzxrO94xwCA ● https://www.youtube.com/watch?v=WdUbXWztKNY ● https://www.youtube.com/watch?v=pBNaWK-ai-M

Slide 35

Slide 35 text

QUESTIONS

Slide 36

Slide 36 text

THANK YOU @petrnohejl, @strvcom

Slide 37

Slide 37 text

No content