Pro Yearly is on sale from $80 to $50! »

How to use MVVM pattern in Android (Droidcon Krakow 2014)

How to use MVVM pattern in Android (Droidcon Krakow 2014)

I would like to show how to use Model-View-ViewModel (MVVM) design pattern on the Android platform. Using this approach UI code is easier to read, test and maintain.

I will show how it can help to:
• remove lots of unnecessary code
• not write boilerplate code any more
• turn Android unit tests running for ages into pure POJO PresentationModels with normal JUnit tests

I will show RoboBinding framework which helps to achieve this goals and how to configure gradle build script to use it.

More information about this talks is available here.

C5f9cc43b0c9c49b5c97d58952b3e225?s=128

Radek Piekarz

December 04, 2014
Tweet

Transcript

  1. How to use MVVM pattern on Android Radosław Piekarz

  2. #droidconKrakow #RoboBinding

  3. None
  4. Android everyday basis this.addButton = (Button) findViewById(R.id.button); this.addButton.setOnClickListener(new View.OnClickListener(){ @Override

    public void onClick(View v) { //do something cool } });
  5. None
  6. Butterknife public class MyActivity extends Activity { @InjectView(R.id.button) Button button;

    //…... @OnClick(R.id.button) void onButtonClicked() { //change the world //or maybe change the UI } // }
  7. Android Annotations @EActivity(R.layout.main_activity) public class MyActivity extends Activity { @ViewById(R.id.button)

    Button button; @Click(R.id.button) public void onButtonClicked() { //change the world //or maybe change the UI } }
  8. Is it enough?

  9. Is it enough? NO!

  10. Model View Presenter • The model is an interface defining

    the data to be displayed • The view is a passive interface that displays data (the model) and routes user commands (events) to the presenter to act upon that data. • The presenter acts upon the model and the view. It retrieves data from repositories (the model), and formats it for display in the view.
  11. Model View Presenter on Android #1 public interface MyView {

    void hideLoading(); void showLoading(); void renderItems(final Collection<Item> items); boolean isReady(); boolean isAlreadyLoaded(); }
  12. Model View Presenter on Android #2 public class MyViewPresenter extends

    Presenter { private MyView view; public void setView(MyView view) { //checking if view is not null etc... this.view = view; } @Override public void initialize() { if(view.isAlreadyLoaded()) { view.showLoading(); } }
  13. Say hello to Model-View-ViewModel

  14. Model-View-ViewModel • The Model, which provides a view-independent representation of

    your business entities. • The View class which is the user interface. It displays information to the user and fires events in response to user interactions. • The ViewModel class, which is the bridge between the view and the model. Each View class has a corresponding ViewModel class.
  15. MVVM on Android #1 public class MyFragmentViewModel { private Listener

    listener; public void initialize() { listener.onVisibilityFlagChanged(true); } public void setListener(Listener listener) { this.listener = listener; } public interface Listener { void onVisibilityFlagChanged(final boolean visible); } }
  16. MVVM on Android #2 public class MyFragment extends BaseFragment implements

    MyFragmentViewModel.Listener { MyFragmentViewModel myFragmentViewModel; @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); bindViewModel(); } private void bindViewModel() { myFragmentViewModel.setListener(this); myFragmentViewModel.initialize(); } @Override public void onVisibilityFlagChanged(boolean visible) { // do some magic
  17. BUT CAN BE BETTER!

  18. MVVM on Android #3 • https://github.com/RoboBinding • https://github.com/gueei/AndroidBinding • https://github.com/kejunxia/Android-Mvvm

    honorable mention: https://github.com/MvvmCross/MvvmCross (Xamarin)
  19. Why RoboBinding? • Still developed and maintained • +400 stars

    at GitHub • Easy to use and extend • Annotation processing and code generation
  20. Robobinding history • Created in 2011 by Robert Taylor &

    Cheng Wei • Added code generation in version 0.8.9 in October 2014
  21. RoboBinding - setup #1 buildscript { repositories { jcenter() mavenCentral()

    maven() { url 'https://oss.sonatype.org/content/repositories/snapshots' } } dependencies { classpath 'com.android.tools.build:gradle:0.14.2' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }
  22. RoboBinding - setup #2 apply plugin: 'com.android.application' apply plugin: 'com.neenbedankt.android-apt'

    apt("org.robobinding:codegen:$robobindingVersion") { exclude group: 'com.google.android', module: 'android' } compile("org.robobinding:robobinding:$robobindingVersion") { exclude group: 'com.google.android', module: 'android' }
  23. Android & RoboBinding - hello world @PresentationModel public class MainViewViewModel

    implements HasPresentationModelChangeSupport { private PresentationModelChangeSupport changeSupport; private String name; public MainViewViewModel() { changeSupport = new PresentationModelChangeSupport(this); } public String getHello() { return name + ": hello Android MVVM(Presentation Model)!"; } public String getName()..... public void setName(String name) …. public void sayHello() { changeSupport.firePropertyChange("hello"); } @Override public PresentationModelChangeSupport getPresentationModelChangeSupport() { return changeSupport; } }
  24. Android meets MVVM - hello world public class MainActivity extends

    Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MainViewViewModel presentationModel = new MainViewViewModel(); View rootView = Binders.inflateAndBindWithoutPreInitializingViews(this, R.layout.activity_main, presentationModel); setContentView(rootView); } }
  25. Android meets MVVM - hello world <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:bind="http://robobinding.org/android"

    tools:ignore="MissingPrefix" android:orientation="vertical"> <TextView …….. bind:text="{hello}"/> <EditText ……. bind:text="${name}"/> <Button …. android:text="Say Hello" bind:onClick="sayHello"/>
  26. ListView, GridView and co. @ItemPresentationModel(value=StringItemPresentationModel.class) public List<String> getItems() { //return

    some items.. } <ListView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" bind:itemLayout="@layout/simple_list_item" bind:source="{items}" />
  27. ListView, GridView and co. #2 public class StringItemPresentationModel implements ItemPresentationModel<String>

    { private String value; @Override public void updateData(String bean, ItemContext itemContext) { value = bean; } public String getValue() { return value; } }
  28. Custom views • No problem at all! • Create custom

    binding or add dynamic binding
  29. Adding new bindings • Just implement PropertyViewAttribute or TwoWayPropertyViewAttribute interface

    if needed • Create binding by implementing ViewBinding interface and map PropertyView classes to the binding name • Register binding
  30. Unit tests • Our ViewModel is separated from UI Android

    dependencies so we create unit test without any problems @Test public void testShouldNotFail() { this.presentationModel.setA("2.0"); this.presentationModel.setB(1.5); assertEquals(expectedValue, this.presentationModel.getResult()); }
  31. Demo time!

  32. RoboBinding Pros • minimize boilerplate code • easy to use

    • easy to extend • fast • pure POJO ViewModels = easy unit tests Cons • still not everything is supported (ListView with multiple item layouts, RecycleView)
  33. Q&A Thank you for your attention! radzio RadoslawPiekarz { }