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

Working with databinding

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Working with databinding

Avatar for Prasham Trivedi

Prasham Trivedi

January 09, 2016
Tweet

More Decks by Prasham Trivedi

Other Decks in Programming

Transcript

  1. MVC • Model - Container for your business data. •

    View - Something that shows model data to end user. • Controller
  2. MVC • Model - Container for your business data. •

    View - Something that shows model data to end user. • Controller - Controls how model data goes to view and how view is affected by model data.
  3. MVC • Model - Regular JavaBeans • View - Activities*,

    Views, Xml • Controller - Activities*, Network layer, DB layer. Activities* - Also fragments since ICS In Android since v1.0
  4. MVVM • Stands for Model, View, ViewModel • Adds functionality

    to Controller of MVC, and make it modular • Does not (entirely) replace role of activities and fragments as controller. • ViewModel defines rule of handling views based on Model. • Leaving controlling part - (Db, Network screen routing) on activities and fragments.
  5. DataBinding • Introduced In Google I/O 2015. • Started with

    android gradle plugin v1.3.0 (Probably), required separate plugin. • Merged with main plugin android gradle plugin v1.5.0
  6. Databinding-Setup • In your project’s build.gradle file, add/upgrade your android

    plugin to v1. 5 classpath 'com.android.tools.build:gradle:1.5.0' • In your module’s build.gradle file update your android{} dsl with databinding.enabled=true android { // Other Logic dataBinding { enabled = true } // Other Logic }
  7. Before Databinding 1- Layouts <LinearLayout ...> <LinearLayout ...> <android.support.design.widget.TextInputLayout ...>

    <EditText android:id="@+id/userNameEditText" .../> </android.support.design.widget.TextInputLayout> <Button android:id="@+id/btnSendVerification" .../> </LinearLayout> </LinearLayout>
  8. Before Databinding 1- Layouts <LinearLayout ...> <LinearLayout ...> <android.support.design.widget.TextInputLayout ...>

    <EditText android:id="@+id/userNameEditText" .../> </android.support.design.widget.TextInputLayout> <Button android:id="@+id/btnSendVerification" .../> </LinearLayout> </LinearLayout>
  9. Before Databinding 2- Java @Override protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); EditText userName = (EditText) findViewById(R.id.userNameEditText); Button sendVerification = (Button) findViewById(R.id. btnSendVerification); sendVerification.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //TODO: Check username is null or not //TODO: Send it to webservice, (if network is there, otherwise save somewhere to send it later) } }); }
  10. Problems • Too much coding. • Too much checks. •

    Error prone. • Butterknife to the rescue • But works on findViewById • Also crashes if error is there
  11. Databinding to the rescue • No FindViewBy ids. • Cast

    automatically. • Can bind properties directly from xml to java code.
  12. After Databinding 1- Layouts <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="login" type="com.celites.aamantran.ViewModels.LoginViewModel"/>

    </data> <LinearLayout ...> <LinearLayout ...> <android.support.design.widget.TextInputLayout ...> <EditText android:id="@+id/userNameEditText" android:hint="@{login.userName}" .../> </android.support.design.widget.TextInputLayout> <Button android:onClick="@{login.verify}" android:id="@+id/btnSendVerification" .../> </LinearLayout> </LinearLayout> </layout>
  13. Before Databinding 1- Layouts <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="login" type="com.celites.aamantran.ViewModels.LoginViewModel"/>

    </data> <LinearLayout ...> <LinearLayout ...> <android.support.design.widget.TextInputLayout ...> <EditText android:id="@+id/userNameEditText" android:hint="@{login.userName}" .../> </android.support.design.widget.TextInputLayout> <Button android:onClick="@{login.verify}" android:id="@+id/btnSendVerification" .../> </LinearLayout> </LinearLayout> </layout>
  14. After Databinding 2- Java @Override protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.activity_login); viewModel = new LoginViewModel(this); binding.setLogin(viewModel); setSupportActionBar(binding.toolBar); }
  15. After Databinding 2- Java @Override protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.activity_login); viewModel = new LoginViewModel(this); binding.setLogin(viewModel); setSupportActionBar(binding.toolBar); }
  16. Button Click Listener. public OnClickListener getVerify() { return verify; }

    OnClickListener verify = new OnClickListener() { @Override public void onClick(View v) { startLogin(); } } };
  17. Working with properties- Defaults • In Xml <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"

    android:text="@{user.firstName}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.lastName}"/> • In Java - User Class public class User { public final String firstName; public final String lastName; public User(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } }
  18. • In Java - Binding MainActivityBinding binding = DataBindingUtil. setContentView(this,

    R.layout.main_activity); User user = new User("Test", "User"); binding.setUser(user);
  19. Rules • Binding Class name = Layout Pascal case name

    + Binding ◦ For layout activity_place_details, binding class name is ActivityPlaceDetailsBinding • For each variable, you need to set data. • For each property, there must be a public getter equivalent to it ◦ E.g. for @{user.firstName} there must be public variable or public getter for it
  20. Two-Way binding* • Only one way binding. From Java to

    Xml. • For Read only presentation. • Can not read-validate form • Can not update status based on child/sibling view’s property *- By default, However it’s possible *
  21. Two-Way binding • By Observables ◦ Not Rx.Observables • Getters

    and setters by default • Runs thread safe • Can bind with existing views.
  22. @BindingAdapter({"binding"}) public static void bindSwitch(CompoundButton button, final BindableBoolean bindableBoolean) {

    button.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { bindableBoolean.set(isChecked); } }); boolean isChecked = bindableBoolean.get(); if (button.isChecked() != isChecked) { button.setChecked(isChecked); } }
  23. @BindingAdapter(value = {"visibleIf", "inverse"}, requireAll = false) public static void

    changeViewDependency(View view, BindableBoolean bool, boolean inverse) { int visibility = bool.get() ? View.VISIBLE : View.GONE; int visibilityInverse = bool.get() ? View.GONE : View.VISIBLE; view.setVisibility((inverse) ? visibilityInverse : visibility); }
  24. /** * Created by Prasham on 10/14/2015. */ public class

    BindableBoolean extends BaseObservable { boolean mValue; public boolean get() { return mValue; } public void set(boolean value) { if (mValue != value) { this.mValue = value; notifyChange(); } } }
  25. BindingAdapter and Observables • Public getters and setters required •

    Get to read value. Set to right value. • Nearly thread safe • Static methods - Errors on duplicate implementation • Single method can listen to multiple attributes. @BindingAdapter Annotation • Can convert from one object to another @BindingConversion Annotation
  26. Custom attributes-Picasso example @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); } <ImageView app:imageUrl=“@{venue.imageUrl}” app:error=“@{@drawable/venueError}”/>
  27. Databinding- As ViewModel • Create a ViewModel from our model

    • Define view rules in view model and expose them as getters • Use view models in xml and refer to rules • Set BindingAdapters, BindingConversions to establish a rule • And again, one binding adapter should be common for whole project
  28. One-way and two-way • One way binding for view only

    adapter rows • Two way binding for forms and views with dynamic behavior
  29. Tips and Tricks • Custom fontfaces using databinding - tip

    from Lisa Wray - https://plus.google. com/+LisaWrayZeitouni/posts/LTr5tX5M9mb • Visibility using Boolean - Tip From Lisa Wray - https://plus.google. com/+LisaWrayZeitouni/posts/5DQGiNbne5W • Tinting - Tip from Luis G Vale - https://plus.google.com/+LuisGonz%C3% A1lezValle/posts/YjUcVJ14Rf5 • Datepicker databinding - George Mount ( A googler) https://halfthought.wordpress. com/2015/10/16/datepicker-data-binding/ • RTL Support - Yours truly - https://plus.google.com/+PrashamTrivedi/posts/gCxFGLV498h