Slide 1

Slide 1 text

How to use MVVM pattern on Android Radosław Piekarz

Slide 2

Slide 2 text

#droidconKrakow #RoboBinding

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

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 } });

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

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 } // }

Slide 7

Slide 7 text

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 } }

Slide 8

Slide 8 text

Is it enough?

Slide 9

Slide 9 text

Is it enough? NO!

Slide 10

Slide 10 text

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.

Slide 11

Slide 11 text

Model View Presenter on Android #1 public interface MyView { void hideLoading(); void showLoading(); void renderItems(final Collection items); boolean isReady(); boolean isAlreadyLoaded(); }

Slide 12

Slide 12 text

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(); } }

Slide 13

Slide 13 text

Say hello to Model-View-ViewModel

Slide 14

Slide 14 text

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.

Slide 15

Slide 15 text

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); } }

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

BUT CAN BE BETTER!

Slide 18

Slide 18 text

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)

Slide 19

Slide 19 text

Why RoboBinding? ● Still developed and maintained ● +400 stars at GitHub ● Easy to use and extend ● Annotation processing and code generation

Slide 20

Slide 20 text

Robobinding history ● Created in 2011 by Robert Taylor & Cheng Wei ● Added code generation in version 0.8.9 in October 2014

Slide 21

Slide 21 text

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 }

Slide 22

Slide 22 text

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' }

Slide 23

Slide 23 text

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; } }

Slide 24

Slide 24 text

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); } }

Slide 25

Slide 25 text

Android meets MVVM - hello world

Slide 26

Slide 26 text

ListView, GridView and co. @ItemPresentationModel(value=StringItemPresentationModel.class) public List getItems() { //return some items.. }

Slide 27

Slide 27 text

ListView, GridView and co. #2 public class StringItemPresentationModel implements ItemPresentationModel { private String value; @Override public void updateData(String bean, ItemContext itemContext) { value = bean; } public String getValue() { return value; } }

Slide 28

Slide 28 text

Custom views ● No problem at all! ● Create custom binding or add dynamic binding

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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()); }

Slide 31

Slide 31 text

Demo time!

Slide 32

Slide 32 text

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)

Slide 33

Slide 33 text

Q&A Thank you for your attention! radzio RadoslawPiekarz { }