The document discusses Android Data Binding and the Model-View-ViewModel (MVVM) pattern. It covers the basics of data binding, using custom attributes with data binding, creating reusable UI components with data binding, implementing two-way data binding, and using data binding with RxJava and the MVVM pattern. The speaker presents code examples for setting up data binding in layout XML files and Java code, and binding data to views while ensuring automatic updates when the data changes.
8. 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
}
11. <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
match_result.xmlMatchResultBinding.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;
// ...
}
12. 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
19. 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
20. 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 everywhere
Can be any View
21. @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}"/>
34. 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
}___
35. 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;
}__
}___
36. <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 && !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>
38. 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
46. 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
}___
47. 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;
}
}___
51. 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;
}__
}___
56. 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);
});
}
}
60. <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);
});
}__
68. 68
Links
developer.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
69. 69
Thanks for your attention!
Questions?
This presentation will be soon available on the droidcon London website at
uk.droidcon.com/#skillscasts