Slide 1

Slide 1 text

Data binding on Android How to use it in the real world

Slide 2

Slide 2 text

Agenda • What, why, how? • Two-way binding • Custom attributes • Event handlers • Architecture • Tips and tricks

Slide 3

Slide 3 text

What, why, how?

Slide 4

Slide 4 text

What is data binding? • Connect data sources with views • Automatic updates (requires some extra effort) • Common approach in other frameworks • WPF & Windows Phone (C#) • Angular (JavaScript)

Slide 5

Slide 5 text

Why use data binding? • Cleaner code • Simple expressions in views • Powerful custom attributes

Slide 6

Slide 6 text

Getting started – Enable data binding android { ... dataBinding { enabled = true } ... }

Slide 7

Slide 7 text

Getting started – Layout setup

Slide 8

Slide 8 text

Getting started – Activity setup @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); DataBindingUtil .setContentView(this, R.layout.activity_main); }

Slide 9

Slide 9 text

Getting started – Activity setup @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); DataBindingUtil .setContentView(this, R.layout.activity_main); } ActivityMainBinding.java

Slide 10

Slide 10 text

Getting started – Activity setup @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding binding = DataBindingUtil .setContentView(this, R.layout.activity_main); User user = new User("George"); binding.setUser(user); }

Slide 11

Slide 11 text

How does it work? • Process layout files • Parse expressions • Generates Java code • Traverses the view hierarchy once to find all views • Keeps a reference to the views

Slide 12

Slide 12 text

Usage • Use it to replace findViewById or Butter Knife @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding binding = DataBindingUtil .setContentView(this, R.layout.activity_main); binding.userName.setText(user.getName()); }

Slide 13

Slide 13 text

Usage • Transforming text android:text="@{String.valueOf(index + 1)}" • Setting views visible based on certain conditions android:visibility="@{user.age < 18 ? View.GONE : View.VISIBLE}" ⚠

Slide 14

Slide 14 text

Usage

Slide 15

Slide 15 text

Dealing with updates – Option 1 public class User { public final ObservableField firstName = new ObservableField<>(); } user.firstName.set("Louise")

Slide 16

Slide 16 text

Dealing with updates – Option 2 public class User extends BaseObservable { private String lastName; @Bindable public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; notifyPropertyChanged(BR.lastName); }

Slide 17

Slide 17 text

Dealing with updates - Internals private long mDirtyFlags = 0xffffffffffffffffL; /* flag mapping flag 0 (0x1L): user.firstName flag 1 (0x2L): user flag 2 (0x3L): user.lastName flag 3 (0x4L): null flag mapping end*/

Slide 18

Slide 18 text

Dealing with updates - Internals public void setUser(User user) { updateRegistration(1, user); this.mUser = user; synchronized(this) { mDirtyFlags |= 0x2L; } notifyPropertyChanged(BR.user); super.requestRebind(); }

Slide 19

Slide 19 text

Dealing with updates - Internals protected void executeBindings() { if ((dirtyFlags & 0xeL) != 0) { if (user != null) { // read user.lastName lastNameUser = user.getLastName(); } } }

Slide 20

Slide 20 text

Two-way binding how to handle user input

Slide 21

Slide 21 text

Two-way binding

Slide 22

Slide 22 text

Custom attributes aka binding adapters

Slide 23

Slide 23 text

Custom attributes – image loading @BindingAdapter({"app:imageUrl", "app:error"}) public static void loadImage(ImageView view, String url, Drawable error { Glide.with(view.getContext()) .load(url) .error(error) .into(view); }

Slide 24

Slide 24 text

Custom attributes – image loading @BindingAdapter({"app:imageUrl", "app:error"}) public static void loadImage(ImageView view, String url, Drawable error { Glide.with(view.getContext()) .load(url) .error(error) .into(view); }

Slide 25

Slide 25 text

Custom attributes – image loading @BindingAdapter({"app:imageUrl", "app:error"}) public static void loadImage(ImageView view, String url, Drawable error { Glide.with(view.getContext()) .load(url) .error(error) .into(view); }

Slide 26

Slide 26 text

Custom attributes – font @BindingAdapter({"app:font"}) public static void setFont(TextView textView, String fontName) { textView .setTypeface(FontCache.getInstance(context) .get(fontName)); } https://github.com/lisawray/fontbinding

Slide 27

Slide 27 text

Custom attributes – animations @BindingAdapter({"app:animatedVisibility"}) public static void setVisibility(View view, int visibility) { … ObjectAnimator alpha = ObjectAnimator.ofFloat(view, View.ALPHA, startAlpha, endAlpha); … alpha.start(); } Full example: https://medium.com/google-developers/android-data-binding-animations-55f6b5956a64

Slide 28

Slide 28 text

Event handlers

Slide 29

Slide 29 text

Event handlers public class UserViewModel { … public View.OnClickListener clickListener; … }

Slide 30

Slide 30 text

Event handlers public class UserViewModel { … public void clickListener(View view) {…} … }

Slide 31

Slide 31 text

Event handlers textChangedListener = new TextWatcher() { public void beforeTextChanged … public void onTextChanged … public void afterTextChanged … }

Slide 32

Slide 32 text

Event handlers

Slide 33

Slide 33 text

Event handlers with parameters public class UserViewModel { public void save(User user) { userRepository.save(user); } }

Slide 34

Slide 34 text

Architecture

Slide 35

Slide 35 text

MVVM View ViewModel Model

Slide 36

Slide 36 text

Data binding MVVM View ViewModel Model getTasks() callback

Slide 37

Slide 37 text

Tips & tricks

Slide 38

Slide 38 text

RecyclerView public class ViewHolder extends RecyclerView.ViewHolder { private final ListItemBinding listItemBinding; public ViewHolder(ListItemBinding binding) { super(binding.getRoot()); this.listItemBinding = binding; } … }

Slide 39

Slide 39 text

RecyclerView public class ViewHolder extends RecyclerView.ViewHolder { private final ListItemBinding listItemBinding; … public void bind(User user) { listItemBinding.setUser(user); listItemBinding.executePendingBindings(); } }

Slide 40

Slide 40 text

RecyclerView public class UserAdapter extends RecyclerView.Adapter { private List users; … @Override public void onBindViewHolder(ViewHolder holder, int position) { User user = users.get(position); holder.bind(user); } }

Slide 41

Slide 41 text

RecyclerView public class MainActivity extends … { @Override protected void onCreate() { ActivityMainBinding binding = DataBindingUtil .setContentView(this, R.layout.activity_main); binding.users.setLayoutManager( new LinearLayoutManager(this)); binding.users.setAdapter(new UserAdapter(users)); } … }

Slide 42

Slide 42 text

RecyclerView advanced @BindingAdapter("items") public static void setItems(RecyclerView recyclerView, Collection items) { BindingRecyclerViewAdapter adapter = (BindingRecyclerViewAdapter) recyclerView.getAdapter(); adapter.setItems(items); }

Slide 43

Slide 43 text

RecyclerView advanced https://github.com/radzio/android-data-binding-recyclerview

Slide 44

Slide 44 text

String formatting Hello, %s

Slide 45

Slide 45 text

Math in expressions

Slide 46

Slide 46 text

Overriding Android attributes @BindingAdapter("android:layout_margin") public static void setMargin(View view, float margin) { MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams(); lp.setMargins(margin, margin, margin, margin); view.setLayoutParams(layoutParams); }

Slide 47

Slide 47 text

Referencing other views

Slide 48

Slide 48 text

Binding conversions @BindingConversion public static int convertBooleanToVisibility(boolean visible) { return visible ? View.VISIBLE : View.GONE; }

Slide 49

Slide 49 text

Resources • Official documentation https://developer.android.com/topic/libraries/data-binding/index.html • George Mount https://medium.com/@georgemount007 • Advanced data binding (Google IO 2016) https://www.youtube.com/watch?v=DAmMN7m3wLU

Slide 50

Slide 50 text

Data binding on Android twitter.com/kevinpelgrims kevinpelgrims.com