69
#droidconUK Android Data Binding in action using MVVM pattern Fabio Collini droidcon London October 2016

Android Data Binding in action using MVVM pattern - droidconUK

Embed Size (px)

Citation preview

Page 1: Android Data Binding in action using MVVM pattern - droidconUK

#droidconUK

Android Data Binding in action using MVVM pattern

Fabio Collini

droidcon London October 2016

Page 2: Android Data Binding in action using MVVM pattern - droidconUK

2

Ego slide

@fabioCollini linkedin.com/in/fabiocollini github.com/fabioCollini medium.com/@fabioCollini codingjam.it

Page 3: Android Data Binding in action using MVVM pattern - droidconUK

3

Agenda

1. Data Binding basics 2. Custom attributes 3. Components 4. Two Way Data Binding 5. Data Binding + RxJava 6. Model View ViewModel

Page 4: Android Data Binding in action using MVVM pattern - droidconUK

#droidconUK - London - October 2016 - @fabioCollini 4

1Data Binding basics

Page 5: Android Data Binding in action using MVVM pattern - droidconUK

Google I/O 2016

5

Google I/O 2015

Page 6: Android Data Binding in action using MVVM pattern - droidconUK

6github.com/fabioCollini/DataBindingInAction

Page 7: Android Data Binding in action using MVVM pattern - droidconUK

7

match_result.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout style="@style/root_layout" xmlns:android=“http://schemas.android.com/apk/res/android"> <ImageView android:id="@+id/result_gif" style="@style/gif"/> <LinearLayout style="@style/team_layout"> <TextView android:id="@+id/home_team" style="@style/name"/> <TextView android:id="@+id/home_goals" style="@style/goals"/> </LinearLayout> <LinearLayout style="@style/team_layout"> <TextView android:id="@+id/away_team" style="@style/name"/> <TextView android:id="@+id/away_goals" style="@style/goals"/> </LinearLayout> </LinearLayout>

Page 8: Android Data Binding in action using MVVM pattern - droidconUK

8

public class TeamScore { private final String name; private final int goals;

//constructor and getters}

public class MatchResult { private final TeamScore homeTeam; private final TeamScore awayTeam; private final String gifUrl;

//constructor and getters}

Page 9: Android Data Binding in action using MVVM pattern - droidconUK

dataBinding { enabled = true }

9

build.gradle

android { //... //... defaultConfig { //...____} buildTypes { //...____}

}

Page 10: Android Data Binding in action using MVVM pattern - droidconUK

<?xml version="1.0" encoding="utf-8"?> <layout> <LinearLayout style=“@style/root_layout" xmlns:android="http://schemas.android.com/apk/res/android"> <ImageView android:id="@+id/result_gif" style="@style/gif"/> <LinearLayout style="@style/team_layout"> <TextView android:id="@+id/home_team" style="@style/name"/> <TextView android:id="@+id/home_goals" style="@style/goals"/> </LinearLayout> <LinearLayout style="@style/team_layout"> <TextView android:id="@+id/away_team" style="@style/name"/> <TextView android:id="@+id/away_goals" style="@style/goals"/> </LinearLayout> </LinearLayout> </layout>

10

Data Binding layout

<LinearLayout style="@style/root_layout" xmlns:android=“http://schemas.android.com/apk/res/android"> <ImageView android:id="@+id/result_gif" style="@style/gif"/> <LinearLayout style="@style/team_layout"> <TextView android:id="@+id/home_team" style="@style/name"/> <TextView android:id="@+id/home_goals" style="@style/goals"/> </LinearLayout> <LinearLayout style="@style/team_layout"> <TextView android:id="@+id/away_team" style="@style/name"/> <TextView android:id="@+id/away_goals" style="@style/goals"/> </LinearLayout> </LinearLayout>

<?xml version="1.0" encoding="utf-8"?><layout>

</layout>

Page 11: Android Data Binding in action using MVVM pattern - droidconUK

<LinearLayout style="@style/root_layout" xmlns:android=“http://schemas.android.com/apk/res/android"> <ImageView android:id="@+id/result_gif" style="@style/gif"/> <LinearLayout style="@style/team_layout"> <TextView android:id="@+id/home_team" style="@style/name"/> <TextView android:id="@+id/home_goals" style="@style/goals"/> </LinearLayout> <LinearLayout style="@style/team_layout"> <TextView android:id="@+id/away_team" style="@style/name"/> <TextView android:id="@+id/away_goals" style="@style/goals"/> </LinearLayout> </LinearLayout>

11

One layout traversal

mat

ch_r

esul

t.xm

lM

atch

Resu

ltBin

ding

.java Auto generated class

<?xml version="1.0" encoding="utf-8"?><layout>

</layout>

public class MatchResultBinding extends android.databinding.ViewDataBinding { // ... public final android.widget.ImageView resultGif; public final android.widget.TextView homeTeam; public final android.widget.TextView homeGoals; public final android.widget.TextView awayTeam; public final android.widget.TextView awayGoals; // ...}

Page 12: Android Data Binding in action using MVVM pattern - droidconUK

12

public class MatchResultActivity extends AppCompatActivity { private MatchResultBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.match_result); MatchResult result = getIntent().getParcelableExtra("RESULT"); if (result.getHomeTeam() != null) { binding.homeTeam.setText(result.getHomeTeam().getName()); binding.homeGoals.setText( Integer.toString(result.getHomeTeam().getGoals())); }if1 if (result.getAwayTeam() != null) { binding.awayTeam.setText(result.getAwayTeam().getName()); binding.awayGoals.setText( Integer.toString(result.getAwayTeam().getGoals())); }if Glide.with(this).load(result.getGifUrl()) .placeholder(R.drawable.loading).into(binding.resultGif); }onCreate}activity

Page 13: Android Data Binding in action using MVVM pattern - droidconUK

13

Variable in layout<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android">

Automatic null check

<data> <variable name="result" type="it.droidcon.databinding.MatchResult"/> </data> <LinearLayout style="@style/root_layout"> <ImageView android:id="@+id/result_gif" style="@style/gif"/> <LinearLayout style="@style/team_layout"> <TextView style=“@style/name" android:text="@{result.homeTeam.name}"/> <TextView style="@style/goals" android:text="@{Integer.toString(result.homeTeam.goals)}"/> </LinearLayout> <LinearLayout style="@style/team_layout"> <TextView style="@style/name" android:text="@{result.awayTeam.name}"/> <TextView style="@style/goals" android:text="@{Integer.toString(result.awayTeam.goals)}"/> </LinearLayout> </LinearLayout> </layout>

Page 14: Android Data Binding in action using MVVM pattern - droidconUK

14

public class MatchResultActivity extends AppCompatActivity { private MatchResultBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.match_result); MatchResult result = getIntent().getParcelableExtra("RESULT");

binding.setResult(result);if Glide.with(this).load(result.getGifUrl()) .placeholder(R.drawable.loading).into(binding.resultGif); }onCreate}activity

Page 15: Android Data Binding in action using MVVM pattern - droidconUK

15

Code in XML? Are you serious?!?

Page 16: Android Data Binding in action using MVVM pattern - droidconUK

16

Complex code in XML is

NOT a best practice

Page 17: Android Data Binding in action using MVVM pattern - droidconUK

#droidconUK - London - October 2016 - @fabioCollini 17

2Custom attributes

Page 18: Android Data Binding in action using MVVM pattern - droidconUK

18

@BindingAdapter

<ImageView android:id="@+id/result_gif" style="@style/gif"/>

Glide.with(this).load(result.getGifUrl()) .placeholder(R.drawable.loading).into(binding.resultGif);

<ImageView style="@style/gif" app:imageUrl="@{result.gifUrl}"/>

@BindingAdapter("imageUrl") public static void loadImage(ImageView view, String url) { Glide.with(view.getContext()).load(url) .placeholder(R.drawable.loading).into(view);}

Page 19: Android Data Binding in action using MVVM pattern - droidconUK

19

public class MatchResultActivity extends AppCompatActivity { private MatchResultBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView( this, R.layout.match_result); MatchResult result = getIntent().getParcelableExtra("RESULT");

binding.setResult(result); }onCreate}activity

Page 20: Android Data Binding in action using MVVM pattern - droidconUK

Annotated methods are static but…

@BindingAdapter("something") public static void bindSomething(View view, AnyObject b) { MyBinding binding = DataBindingUtil.findBinding(view); MyObject myObject = binding.getMyObject(); //… TextView myTextView = binding.myTextView; //… }

Can be any object

Get the layout binding

Get the connected objects

Access to all the views

Can be defined anywhere Can be used everywhereCan be any View

Page 21: Android Data Binding in action using MVVM pattern - droidconUK

@BindingAdapter("goals") public static void bindGoals(TextView view, int goals) { view.setText(Integer.toString(goals));}__

21

BindingAdapter

<TextView style="@style/goals" android:text="@{Integer.toString(result.awayTeam.goals)}"/>

<TextView style="@style/goals" app:goals="@{result.awayTeam.goals}"/>

Page 22: Android Data Binding in action using MVVM pattern - droidconUK

#droidconUK - London - October 2016 - @fabioCollini 22

3Components

Page 23: Android Data Binding in action using MVVM pattern - droidconUK

23

<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="result" type="it.droidcon.databinding.MatchResult"/> </data> <LinearLayout style="@style/root_layout"> <ImageView style="@style/gif" app:imageUrl="@{result.gifUrl}"/>

<LinearLayout style="@style/team_layout"> <TextView style="@style/name" android:text="@{result.awayTeam.name}"/> <TextView style="@style/goals" app:goals="@{result.awayTeam.goals}"/> </LinearLayout> </LinearLayout> </layout>

<LinearLayout style="@style/team_layout"> <TextView style="@style/name" android:text="@{result.homeTeam.name}"/> <TextView style="@style/goals" app:goals="@{result.homeTeam.goals}"/> </LinearLayout>

Page 24: Android Data Binding in action using MVVM pattern - droidconUK

24

<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">

</layout>

team_detail.xml

<data> <variable name="team" type="it.droidcon.databinding.TeamScore"/> </data>

<LinearLayout style="@style/team_layout"> <TextView style="@style/name" android:text="@{team.name}"/> <TextView style="@style/goals" app:goals="@{team.goals}"/> </LinearLayout>

Page 25: Android Data Binding in action using MVVM pattern - droidconUK

</data> <LinearLayout style="@style/root_layout"> <ImageView style="@style/gif" app:imageUrl="@{result.gifUrl}"/>

<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:bind="http://schemas.android.com/tools"> <data> <variable name="result" type="it.droidcon.databinding.MatchResult"/>

<include layout="@layout/team_detail" /> <include layout="@layout/team_detail" /> </LinearLayout> </layout>

bind:team="@{result.homeTeam}"

bind:team="@{result.awayTeam}"

Page 26: Android Data Binding in action using MVVM pattern - droidconUK

#droidconUK - London - October 2016 - @fabioCollini 26

4Two Way Data Binding

Page 27: Android Data Binding in action using MVVM pattern - droidconUK

27

Page 28: Android Data Binding in action using MVVM pattern - droidconUK

28

public class QuestionInfo { public String answer = ""; public int countdown = 10;

public int decrementCountdown() { return --countdown; }_ }_

Page 29: Android Data Binding in action using MVVM pattern - droidconUK

29

public class QuestionInfo { public String answer = ""; public int countdown = 10;

public int decrementCountdown() { return --countdown; }_ }_

<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="info" type="it.droidcon.databinding.question.QuestionInfo"/> </data> <LinearLayout style="@style/form_root"> <TextView style="@style/question"/> <EditText style="@style/answer" android:text="@{info.answer}" /> <Button style="@style/form_button" android:enabled="@{info.countdown > 0 &amp;&amp; !info.answer.empty}"/> <TextView style="@style/countdown" android:text="@{Integer.toString(info.countdown)}" /> </LinearLayout> </layout>

Page 30: Android Data Binding in action using MVVM pattern - droidconUK

public class QuestionActivity extends AppCompatActivity { private QuestionInfo info; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); QuestionBinding binding = DataBindingUtil.setContentView(this, R.layout.question); info = new QuestionInfo(); binding.setInfo(info); Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { int newValue = info.decrementCountdown(); if (newValue > 0) { handler.postDelayed(this, 1000); } } }, 1000); } } 30

public class QuestionInfo { public String answer = ""; public int countdown = 10;

public int decrementCountdown() { return --countdown; }_ }_

Page 31: Android Data Binding in action using MVVM pattern - droidconUK

31

Page 32: Android Data Binding in action using MVVM pattern - droidconUK

32

Views are not automatically updated :(

package android.databinding;public interface Observable { void addOnPropertyChangedCallback( OnPropertyChangedCallback callback); void removeOnPropertyChangedCallback( OnPropertyChangedCallback callback); abstract class OnPropertyChangedCallback { public abstract void onPropertyChanged( Observable sender, int propertyId); }}

Page 33: Android Data Binding in action using MVVM pattern - droidconUK

33

Observable hierarchy

Page 34: Android Data Binding in action using MVVM pattern - droidconUK

34

public class QuestionInfo extends BaseObservable {_ private String answer = ""; private int countdown = 10; public int decrementCountdown() { --countdown; notifyPropertyChanged(BR.countdown); return countdown; }__ @Bindable public String getAnswer() { return answer; }getAnswer public void setAnswer(String answer) { this.answer = answer; notifyPropertyChanged(BR.answer); }setAnswer @Bindable public int getCountdown() { return countdown; }getCountdown}___

Page 35: Android Data Binding in action using MVVM pattern - droidconUK

35

public class QuestionInfo {_ public final ObservableField<String> answer = new ObservableField<>(""); public final ObservableInt countdown = new ObservableInt(10); public int decrementCountdown() { int value = countdown.get() - 1; countdown.set(value); return value; }__ }___

Page 36: Android Data Binding in action using MVVM pattern - droidconUK

<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="info" type="it.droidcon.databinding.question.QuestionInfo"/> </data> <LinearLayout style="@style/form_root"> <TextView style="@style/question"/> <EditText style="@style/answer" android:text="@{info.answer}" /> <Button style="@style/form_button" android:enabled="@{info.countdown > 0 &amp;&amp; !info.answer.empty}"/> <TextView style="@style/countdown" android:text="@{Integer.toString(info.countdown)}" /> </LinearLayout> </layout>

36

ObservableField<String>

ObservableInt

ObservableInt

public class QuestionInfo {_ public final ObservableField<String> answer = new ObservableField<>(""); public final ObservableInt countdown = new ObservableInt(10); public int decrementCountdown() { int value = countdown.get() - 1; countdown.set(value); return value; }__ }___

ObservableField<String>

Page 37: Android Data Binding in action using MVVM pattern - droidconUK

37

Page 38: Android Data Binding in action using MVVM pattern - droidconUK

38

Two way Data Binding@BindingAdapter("binding") public static void bindEditText(EditText view, final ObservableString observable) { Pair<ObservableString, TextWatcherAdapter> pair = (Pair) view.getTag(R.id.bound_observable); if (pair == null || pair.first != observable) { if (pair != null) view.removeTextChangedListener(pair.second); TextWatcherAdapter watcher = new TextWatcherAdapter() { @Override public void onTextChanged(CharSequence s, int a, int b, int c) { observable.set(s.toString()); } }; view.setTag(R.id.bound_observable, new Pair<>(observable, watcher)); view.addTextChangedListener(watcher); } String newValue = observable.get(); if (!view.getText().toString().equals(newValue)) view.setText(newValue);}

medium.com/@fabioCollini/android-data-binding-f9f9d3afc761

Page 39: Android Data Binding in action using MVVM pattern - droidconUK

39

Page 40: Android Data Binding in action using MVVM pattern - droidconUK

<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="info" type="it.droidcon.databinding.question.QuestionInfo"/> </data> <LinearLayout style="@style/form_root"> <TextView style="@style/question"/> <EditText style="@style/answer" android:text="@={info.answer}" /> <Button style="@style/form_button" android:enabled="@{info.countdown > 0 &amp;&amp; !info.answer.empty}"/> <TextView style="@style/countdown" android:text="@{Integer.toString(info.countdown)}" /> </LinearLayout> </layout>

40

Two way data binding

Page 41: Android Data Binding in action using MVVM pattern - droidconUK

41

Page 42: Android Data Binding in action using MVVM pattern - droidconUK

42

Page 43: Android Data Binding in action using MVVM pattern - droidconUK

43

Layout

QuestionInfo

Binding

Text

Wat

cher

set(…

)addOnProperty

ChangedCallbackset(…)

if (changed)

WeakReference

if (changed)

Page 44: Android Data Binding in action using MVVM pattern - droidconUK

#droidconUK - London - October 2016 - @fabioCollini 44

5Data Binding + RxJava

Page 45: Android Data Binding in action using MVVM pattern - droidconUK

45

<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="info" type="it.droidcon.databinding.question.QuestionInfo"/> </data> <LinearLayout style="@style/form_root"> <TextView style="@style/question"/> <EditText style="@style/answer" android:text="@={info.answer}" /> <Button style="@style/form_button" android:enabled="@{info.countdown > 0 &amp;&amp; !info.answer.empty}"/> <TextView style="@style/countdown" android:text="@{Integer.toString(info.countdown)}" /> </LinearLayout> </layout>

Page 46: Android Data Binding in action using MVVM pattern - droidconUK

public class QuestionInfo extends BaseObservable {_ private String answer = ""; private int countdown = 10; public int decrementCountdown() { --countdown; notifyPropertyChanged(BR.countdown); notifyPropertyChanged(BR.sendEnabled); return countdown; }__ @Bindable public String getAnswer() { return answer; }getAnswer public void setAnswer(String answer) { this.answer = answer; notifyPropertyChanged(BR.answer); notifyPropertyChanged(BR.sendEnabled); }setAnswer @Bindable public int getCountdown() { return countdown; }getCountdown

@Bindable public boolean isSendEnabled() { return !answer.isEmpty() && countdown > 0; }isButtonEnabled}___

Page 47: Android Data Binding in action using MVVM pattern - droidconUK

47

Not an Observable, View is not updated!

public class QuestionInfo {_ public final ObservableField<String> answer = new ObservableField<>(""); public final ObservableInt countdown = new ObservableInt(10); public int decrementCountdown() { int value = countdown.get() - 1; countdown.set(value); return value; }__ public boolean isSendEnabled() { return !answer.get().isEmpty() && countdown.get() > 0; } }___

Page 48: Android Data Binding in action using MVVM pattern - droidconUK

48

RxJava FTW!

Page 49: Android Data Binding in action using MVVM pattern - droidconUK

ObservableField<T> rx.Observable<T>

Page 50: Android Data Binding in action using MVVM pattern - droidconUK

50

ObservableField<T> rx.Observable<T>

public static <T> rx.Observable<T> toRx(ObservableField<T> observableField) { return rx.Observable.fromEmitter(emitter -> { emitter.onNext(observableField.get()); OnPropertyChangedCallback callback = new OnPropertyChangedCallback() { @Override public void onPropertyChanged(Observable observable, int i) { emitter.onNext(((ObservableField<T>) observable).get()); } }; observableField.addOnPropertyChangedCallback(callback); emitter.setCancellation(() -> observableField.removeOnPropertyChangedCallback(callback)); }, Emitter.BackpressureMode.BUFFER);}

Page 51: Android Data Binding in action using MVVM pattern - droidconUK

51

public class QuestionInfo {_ public final ObservableField<String> answer = new ObservableField<>(""); public final ObservableInt countdown = new ObservableInt(10);

public final ObservableBoolean sendEnabled = new ObservableBoolean(); public int decrementCountdown() { int value = countdown.get() - 1; countdown.set(value); return value; }__ }___

Page 52: Android Data Binding in action using MVVM pattern - droidconUK

52

public class QuestionActivity extends AppCompatActivity { private QuestionInfo info; private Subscription subscription; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { //... } @Override protected void onStart() { super.onStart(); subscription = Observable.combineLatest( toRx(info.answer), toRx(info.countdown), (answer, countdown) -> !answer.isEmpty() && countdown > 0 ).subscribe(info.sendEnabled::set); } @Override protected void onStop() { super.onStop(); subscription.unsubscribe(); }}

Page 53: Android Data Binding in action using MVVM pattern - droidconUK

53

compile 'com.cantrowitz:rxbroadcast:1.0.0'

public class ConnectionChecker { private Context context; public ConnectionChecker(Context context) { this.context = context; } public Observable<Boolean> getConnectionStatus() { IntentFilter filter = new IntentFilter( ConnectivityManager.CONNECTIVITY_ACTION); return RxBroadcast.fromBroadcast(context, filter) .map(i -> getNetworkInfo()) .map(info -> info != null && info.isConnected()) .distinctUntilChanged(); } private NetworkInfo getNetworkInfo() { ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); return connectivityManager.getActiveNetworkInfo(); }}

Page 54: Android Data Binding in action using MVVM pattern - droidconUK

public class QuestionActivity extends AppCompatActivity { private QuestionInfo info; private Subscription subscription; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { //... }onCreate @Override protected void onStart() { super.onStart(); subscription = Observable.combineLatest( toRx(info.answer), toRx(info.countdown), connectionChecker.getConnectionStatus(), (answer, countdown, connected) -> !answer.isEmpty() && countdown > 0 && connected ).subscribe(info.sendEnabled::set); }onStart @Override protected void onStop() { super.onStop(); subscription.unsubscribe(); }onStop}_

54

Page 55: Android Data Binding in action using MVVM pattern - droidconUK

#droidconUK - London - October 2016 - @fabioCollini 55

6MVVM

Page 56: Android Data Binding in action using MVVM pattern - droidconUK

56

MatchResultViewModel

public class MatchResultViewModel { public final ObservableField<MatchResult> result = new ObservableField<>(); public final ObservableBoolean loading = new ObservableBoolean(); public void reload() { loading.set(true); reloadInBackground(result -> { loading.set(false); this.result.set(result); }); } }

Page 57: Android Data Binding in action using MVVM pattern - droidconUK

<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:bind="http://schemas.android.com/tools"> <data> <variable name="viewModel" type="it.droidcon.databinding.MatchResultViewModel"/> </data> <LinearLayout style="@style/root_layout"> <ImageView style="@style/gif" app:imageUrl="@{viewModel.result.gifUrl}"/>

<include layout="@layout/team_detail" /> <include layout="@layout/team_detail" /> </LinearLayout> </layout>

bind:team="@{viewModel.result.homeTeam}"

bind:team="@{viewModel.result.awayTeam}"

ObservableField

Page 58: Android Data Binding in action using MVVM pattern - droidconUK

58

Visibility

<FrameLayout style="@style/progress_layout" android:visibility= "@{viewModel.loading ? View.VISIBLE : View.GONE}"> <ProgressBar style="@style/progress"/></FrameLayout>

<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:bind="http://schemas.android.com/tools"> <data> <import type="android.view.View"/> <variable name="viewModel" type="it.droidcon.databinding.MatchResultViewModel"/> </data> <FrameLayout style="@style/main_container"> <LinearLayout style="@style/root_layout"> <!-- ... --> </LinearLayout>

</FrameLayout> </layout>

Page 59: Android Data Binding in action using MVVM pattern - droidconUK

59

Visibility

<FrameLayout style="@style/progress_layout" app:visibleOrGone="@{viewModel.loading}"> <ProgressBar style="@style/progress"/></FrameLayout>

@BindingAdapter("visibleOrGone") public static void bindVisibleOrGone(View view, boolean b) { view.setVisibility(b ? View.VISIBLE : View.GONE); }____

@BindingAdapter("visible") public static void bindVisible(View view, boolean b) { view.setVisibility(b ? View.VISIBLE : View.INVISIBLE); }

Page 60: Android Data Binding in action using MVVM pattern - droidconUK

<LinearLayout style="@style/root_layout" android:onClick="@{???}"> <!-- ... --></LinearLayout>

60

}___

public class MatchResultViewModel {

public final ObservableField<MatchResult> result = new ObservableField<>();

public final ObservableBoolean loading = new ObservableBoolean();

public void reload() { loading.set(true); reloadInBackground(result -> { loading.set(false); this.result.set(result); }); }__

Page 61: Android Data Binding in action using MVVM pattern - droidconUK

<LinearLayout style="@style/root_layout" android:onClick="@{v -> viewModel.reload()}"> <!-- ... --></LinearLayout>

61

public void reload() { //.. }__

<LinearLayout style="@style/root_layout" android:onClick=“@{viewModel::reload}”> <!-- ... --></LinearLayout>

public void reload(View v) { //.. }__

@BindingAdapter("android:onClick") public static void bindOnClick(View view, final Runnable listener) { view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listener.run(); }____ });}___

<LinearLayout style="@style/root_layout" android:onClick=“@{viewModel::reload}”> <!-- ... --></LinearLayout>

public void reload() { //.. }__

Page 62: Android Data Binding in action using MVVM pattern - droidconUK

62

Final layout<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:bind="http://schemas.android.com/tools"> <data> <!-- ... --> </data> <FrameLayout style="@style/main_container"> <LinearLayout style="@style/root_layout" android:onClick=“@{viewModel::reload}”> <!-- ... --> </LinearLayout> <FrameLayout style="@style/progress_layout" app:visibleOrGone="@{viewModel.loading}"> <ProgressBar style="@style/progress"/> </FrameLayout> </FrameLayout> </layout>

Page 63: Android Data Binding in action using MVVM pattern - droidconUK

63

Model View ViewModel

View

ViewModel

Model

DataBinding

Retained on configuration change

Saved in Activity or Fragment state

Activity or Fragment

Page 64: Android Data Binding in action using MVVM pattern - droidconUK

64

MVVM

View

ViewModel

Model

DataBinding

View

Presenter

Model

MVPVs

Page 65: Android Data Binding in action using MVVM pattern - droidconUK

MVVM MVPVs

Less Java code

if (view != null)

A/B testing on View

Sometimes we need an Activity :(

Testable code Testable code

Less XML

No more

Page 66: Android Data Binding in action using MVVM pattern - droidconUK

66

github.com/fabioCollini/LifeCycleBinder

Move your Android code to testable Java classes

Page 67: Android Data Binding in action using MVVM pattern - droidconUK

Custom attributes Reusable UI code

67

Data binding

Includes UI componentsRxJava Easy composition

Page 68: Android Data Binding in action using MVVM pattern - droidconUK

68

Linksdeveloper.android.com/tools/data-binding/guide.html

Google I/O 2015 - What's new in Android Data Binding -- Write Apps Faster (Android Dev Summit 2015) Advanced Data Binding - Google I/O 2016

George Mount medium profile

Radosław Piekarz: RxJava meets Android Data Binding

Florina Muntenescu: A Journey Through MV Wonderland Bill Phillips: Shades of MVVM

Page 69: Android Data Binding in action using MVVM pattern - droidconUK

69

Thanks for your attention!

Questions?

This presentation will be soon available on the droidcon London website at

uk.droidcon.com/#skillscasts