Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Binding Data with Android Databinding

Binding Data with Android Databinding

Slide of the talk I gave at GDG Milano DevFest 2015.

Riccardo Ciovati

October 03, 2015
Tweet

More Decks by Riccardo Ciovati

Other Decks in Programming

Transcript

  1. Whoami • I have been building Android apps for more

    than 5 years • Android Developer at Subito • GDG Milano manager since April 2015
  2. Data Binding is a way to get your data from

    your data model into your UI using (almost) just markup. What’s Data Binding?
  3. How we did it so far? <?xml version="1.0" encoding="utf-8"?> <LinearLayout

    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/ad_subject" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
  4. How we did it so far? public class MainActivity extends

    AppCompatActivity { private Ad mAd = new Ad("iPhone for sale"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView subject = (TextView) findViewById(R.id.ad_subject); subject.setText(mAd.getSubject()); } }
  5. What’s wrong with this? • Could crash at runtime ◦

    Missing ID ◦ Wrong cast ◦ Multiple layout configurations can have different elements • Each findViewById requires a layout traversal • Only the main thread can access those elements • It’s boilerplate code ◦ A few libraries to the rescue (eg Butterknife)
  6. Hello Data Binding <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable

    name="ad" type="it.subito.model.Ad"/> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:text="@{ad.subject}" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> </layout>
  7. Hello Data Binding public class MainActivity extends AppCompatActivity { private

    Ad mAd = new Ad("iPhone for sale"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.setAd(mAd); } }
  8. Hello Data Binding • • • • • • •

    • Code generator + small runtime dependency • Works with API level 7+ apply plugin: 'com.android.databinding' buildscript { repositories { jcenter() } dependencies { classpath "com.android.databinding:dataBinder:1.0-rc2" } }
  9. • Most Java expressions are supported: ◦ String concatenation: +

    ◦ Logical operator: &&, || ◦ Comparision: ==, =>, <=, ect • Method invocation and field access • Built-in null-safety and null-coalescing operator: ◦ android:text="@{ad.subject ?? @string/no_subject}" • Expressions autocomplete in AS is not supported (yet) • Syntax checks at compile-time Full List: https://goo.gl/9FVASg Expressions - Basics
  10. Expressions - Method invocation <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data>

    <variable name="ad" type="it.subito.model.Ad"/> <import type="android.text.format.DateUtils"/> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:text="@{DateUtils.getRelativeTimeSpanString(ad.insertionDate)}" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> </layout>
  11. Expressions - Arrays and Maps <data> <import type="android.util.SparseArray"/> <import type="java.util.Map"/>

    <import type="java.util.List"/> <variable name="list" type="List&lt;String>"/> <variable name="sparse" type="SparseArray&lt;String>"/> <variable name="map" type="Map&lt;String, String>"/> <variable name="index" type="int"/> <variable name="key" type="String"/> </data> android:text="@{list[index]}" android:text="@{sparse[index]}" android:text="@{map[key]}"
  12. Model-View-ViewModel is an architectural pattern which allows to to separate

    and mediate the communication between model and views. • Separation of presentation logic and business logic • Testability Source: https://goo.gl/d0oxj7 MVVM MVVM picture
  13. One way: model values are automatically assigned to the UI

    placeholder elements specified through the data binding notation, but the UI elements don't change the values in the model. Changes in the model are not propagated to the view. Source: https://goo.gl/fo3797 Databinding models One-Way Data Binding
  14. Two way: model values are automatically assigned to the UI

    placeholder elements specified through the data binding notation. Any changes to the view are immediately reflected in the model, and any changes in the model are propagated to the view. Source: https://goo.gl/fo3797 Databinding models Two-Way Data Binding
  15. One and a half way databinding The Data Binding Library

    provides a mechanism to implement an hybrid approch between one-way and two-way databinding in wich model changes are reflected to the UI. To implement that we have two options: • Using Observable Objects • Using Observable Fields
  16. Observable Objects public class Ad extends BaseObservable { private String

    mSubject; public void setSubject(String subject) { mSubject = subject; notifyPropertyChanged(BR.subject); } @Bindable public String getSubject() { return mSubject; } }
  17. Observable Objects • We need to annotate each getter with

    the @Bindable annotation provided by the Data Binding Library and notify the changes in the setter. • For each method annotated the compiler will generate a corrisponding field in the BR class. If case we don’t want or we can’t extend from BaseObservable we can implement the Observable interface.
  18. Observable Fields • Built-in Observable types: ObservableField<T>, ObservableBoolean, ObservableByte, ObservableChar,

    ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, and ObservableParcelable. public class Ad { public final ObservableField<String> subject = new ObservableField<>(); } //Setting the value will refresh the components observing this field mAd.subject.set("iPhone for sale");
  19. Observable Collections • ObservableList ◦ ObservableArrayList is the implementation ◦

    Notify whether items are added, changed, moved or removed • ObservableMap ◦ ObservableArrayMap is the implementation ◦ Notify whether a key is added, removed or changed.
  20. • You don’t have to take care to set Observables

    fields from the main thread, the Data Binding Library will dispatch notifications in the main thread for you. Observable Fields
  21. Binding Adapter • • • • • • • <?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"> <data> <variable name="ad" type="it.subito.Ad"/> <variable name="loading" type="android.databinding.ObservableBoolean"/> </data> <ViewAnimator app:displayedChild="@{loading.get() ? 0 : 1}"> <ProgressBar /> <TextView android:text="@{ad.subject}"/> </ViewAnimator> </layout>
  22. Binding Adapter • • • • • • • <?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"> <data> <variable name="ad" type="it.subito.Ad"/> <variable name="loading" type="android.databinding.ObservableBoolean"/> </data> <ViewAnimator app:displayedChild="@{loading.get() ? 0 : 1}"> <ProgressBar /> <TextView android:text="@{ad.subject}"/> </ViewAnimator> </layout>
  23. Binding Adapter • Namespace is actually not taken into account

    • Cool examples: ◦ Setting custom typeface: https://goo.gl/H9v1vA ◦ Binding collection to ListView/RecyclerView: https://goo.gl/zQl94z @BindingAdapter("bind:displayedChild") public static void setDisplayedChild(ViewAnimator viewAnimator, int index) { viewAnimator.setDisplayedChild(index); }
  24. Binding Adapter • You read parameters from multiple attributes at

    once @BindingAdapter({"bind:imageUrl", "bind:error"}) public static void loadImage(ImageView view, String url, Drawable error) { Picasso.with(view.getContext()).load(url).error(error).into(view); }
  25. Summary • Databinding allows you to rethink your app architecture

    in a more robust and testable way • Keep away your business logic from you views → MVVM • Tools are currently under development so expect big enhacements in the future
  26. References and further reading • Databinding Guide: https://goo.gl/2s693c • Building

    Apps Faster with Android Data Binding: https://goo.gl/zkyNwA • Data Binding Techniques @ Droidcon NYC, 2015: https://goo.gl/WsmIYc • Android Databinding: goodbye Presenter, hello ViewModel: http://goo. gl/xnqDWt • MVVM on Android using the Data Binding Library: http://goo.gl/qCXFRc