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

Data Binding in Android

Data Binding in Android

Ihor Dzikovskyy

January 21, 2017
Tweet

More Decks by Ihor Dzikovskyy

Other Decks in Programming

Transcript

  1. What is Data Binding Data Binding is a technique that

    allows us to connect our Ui elements and a data model
  2. Data Binding in Android • Introduced in Android Marshmallow •

    The Data Binding Library is a support library (can be used with Android API level 7+) • Android Plugin for Gradle 1.5.0-alpha1 or higher is required • Android Studio 1.3 and later provides support for data binding
  3. Getting Ready • Download the support repository using the SDK

    manager • Add the dataBinding element to your app build.gradle file, as shown in the snippet below
  4. Data Binding in Activity ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); Data

    Binding inside a ListView or RecyclerView adapter ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false); //or ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
  5. How it works? All code generation and expression parsing happens

    at compile time => if an expression has error the project won't compile No reflection, no runtime overhead
  6. Listener Bindings Binding expressions that run when an event happens

    Similar to method references, but they let you run arbitrary data binding expressions. Available with Android Gradle Plugin for Gradle version 2.0 and later Only your return value must match the expected return value of the listener (unless it is expecting void)
  7. Listener Bindings Listeners are represented by lambda expressions public class

    Presenter { public void onSaveClick(Task task){} } android:onClick="@{() -> presenter.onSaveClick(task)}"
  8. Listener Bindings You can either ignore all parameters to the

    method or name all of them public class Presenter { public void onSaveClick(View view, Task task){} } android:onClick="@{(v) -> presenter.onSaveClick(v, task)}"
  9. Listener Bindings You can either ignore all parameters to the

    method or name all of them public class Presenter { public void completeChanged(Task task, boolean completed){} } <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />
  10. Listener Bindings Your expressions must return the same type of

    value as well public class Presenter { public boolean onLongClick(View view, Task task){} } android:onLongClick="@{(view) -> presenter.onLongClick(view, task)}"
  11. Imports <data> <import type="android.view.View"/> <variable name="user" type="com.example.User"/> </data> <TextView android:text="@{user.lastName}"

    android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>
  12. Imports, alias <data> <import type="android.view.View" alias="v1"/> <import type="com.example.View" alias="v2"/> <variable

    name="user" type="com.example.User"/> </data> <TextView android:text="@{user.lastName}" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="@{user.isAdult ? v1.VISIBLE : v1.GONE}"/>
  13. Expression Language • Mathematical + - / * % •

    String concatenation + • Logical && || • Binary & | ^ • Unary + - ! ~ • Shift >> >>> << • Comparison == > < >= <= • instanceof • Grouping () • Literals - character, String, numeric, null • Cast • Method calls • Field access • Array access [] • Ternary operator ?:
  14. Observable Objects public class User extends BaseObservable { private String

    name; @Bindable public String getName() { return name; } public void setName(String name) { this.name = name; notifyPropertyChanged(BR.name); } }
  15. ObservableFields private static class User { public final ObservableField<String> firstName

    = new ObservableField<>(); public final ObservableField<String> lastName = new ObservableField<>(); public final ObservableInt age = new ObservableInt(); } user.firstName.set("John"); int age = user.age.get();
  16. Custom attributes, BindingAdapter <ImageView android:src="@{user.pictureUrl}" /> @BindingAdapter("android:src") public static void

    loadImage(ImageView view, String imageUrl) { Picasso.with(view.getContext()) .load(imageUrl) .into(view); }
  17. BindingAdapter, BindingAdapter @BindingAdapter({"android:src", "app:error"}) public static void loadImage(ImageView view, String

    url, Drawable error) { Picasso.with(view.getContext()) .load(url) .error(error) .into(view); }
  18. Working with RecyclerView public class MyViewHolder extends RecyclerView.ViewHolder { private

    final ItemBinding binding; public MyViewHolder(ItemBinding binding) { super(binding.getRoot()); this.binding = binding; } public void bind(Item item) { binding.setItem(item); binding.executePendingBindings(); } }
  19. Working with RecyclerView public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); ItemBinding itemBinding = ItemBinding.inflate(layoutInflater, parent, false); return new MyViewHolder(itemBinding); } public void onBindViewHolder(MyViewHolder holder, int position) { Item item = getItemForPosition(position); holder.bind(item); }
  20. Working with RecyclerView executePendingBindings() - forces the bindings to run

    immediately instead of delaying them until the next frame
  21. Reusing the ViewHolder public class MyViewHolder extends RecyclerView.ViewHolder { private

    final ViewDataBinding binding; public MyViewHolder(ViewDataBinding binding) { super(binding.getRoot()); this.binding = binding; } public void bind(Object obj) { binding.setVariable(BR.obj, obj); binding.executePendingBindings(); } } <variable name="obj" type="Item"/>
  22. Pros and Cons + • Eliminates much boilerplate • Powerful,

    easy to implement custom attributes • Compile time validation • Performance - faster than findViewById • Reusable methods and adapters - • Presentation logic on the layout • Harder to debug • The auto-generated .class increases app size • IDE integration • Refactoring