Pro Yearly is on sale from $80 to $50! »

talk:title="@{dataBinding}

0ebcda68732e9ed18d903d34bcf62b64?s=47 Lisa Wray
February 09, 2016

 talk:title="@{dataBinding}

A tour through the data binding framework's obvious and not-so-obvious perks. Reduce boilerplate, avoid NullPointerExceptions, decrease code complexity, and maybe even fix some Android pet peeves.

0ebcda68732e9ed18d903d34bcf62b64?s=128

Lisa Wray

February 09, 2016
Tweet

Transcript

  1. “@{dataBinding}” talk:title= @{dataBinding} @lisawrayz

  2. textView.setCompoundDrawablesWithIntrinsicBounds( ContextCompat.getDrawable(this, R.drawable.cat), null, null, null); Problem: Repetitive Java boilerplate

    @{dataBinding} findViewById, casts setters are verbose/confusing toolbar = (Toolbar) findViewById(R.id.toolbar);
  3. Problem: Repetitive Java boilerplate @{dataBinding} findViewById, casts setters are verbose/confusing

    XML layout is limited Manually keep track of UI updates
  4. What is it? @{dataBinding} A framework to connect your model

    and your UI Once or persistently
  5. An XML attribute for every Java setter @{dataBinding} What else

    is it?
  6. Custom XML attributes @{dataBinding} What else is it?

  7. Overwrite Android XML attributes @{dataBinding} What else is it?

  8. An alternative to custom views @{dataBinding} What else is it?

  9. O.K., show me!

  10. Find the views Set custom font Set button colors Load

    and set the image Set title
  11. Before: inflate and find views CollapsingToolbarLayout appBarLayout = (CollapsingToolbarLayout) findViewById(R.id.toolbar_layout);

    ImageView backdropImageView = (ImageView) findViewById(R.id.backdrop); Button upvoteButton = (Button) findViewById(R.id.upvote); Button downvoteButton = (Button) findViewById(R.id.downvote); setContentView(R.layout.activity_pet_detail); After PetDetailBinding binding = DataBindingUtil.setContentView (this, R.layout.pet_detail);
  12. Before:Java if (pet != null) { appBarLayout.setTitle(pet.getName()); } After:XML <android.support.design.widget.CollapsingToolbarLayout

    app:title="@{pet.name}" >
  13. Before: Java Typeface lobster = FontCache.getInstance().get("LobsterTwo-Bold"); appBarLayout.setCollapsedTitleTypeface(lobster); appBarLayout.setExpandedTitleTypeface(lobster); After:XML <android.support.design.widget.CollapsingToolbarLayout

    app:collapsedTitleTypeface="@{`LobsterTwo-Bold`}" app:expandedTitleTypeface=“@{`LobsterTwo-Bold`}" >
  14. <Button app:selected=“@{vote == VOTE.UPVOTE}" android:tint=“@drawable/upvote_selector” /> Before:Java After:XML switch(pet.vote) {

    case UPVOTE: upvoteButton.setSelected(true); downvoteButton.setSelected(false); break; case DOWNVOTE: …
  15. Before: Java Glide.with(this).load(pet.getImageUrl()).into(backdropImageView); After:XML <ImageView app:imageUrl="@{pet.imageUrl}"/>

  16. Making the connection

  17. PetDetailBinding binding = DataBindingUtil.setContentView (this, R.layout.pet_detail); Before: Java … <layout>

    <data> <variable name="pet" type="com.xwray.dogmeetscat.Pet"/> </data> After:XML </layout> binding.setPet(pet); PetDetailBinding binding = DataBindingUtil.setContentView (this, R.layout.pet_detail); Your old layout goes here Your model object
  18. 100% generated Java code Uses bitwise flags to mark ‘dirty’

    One traversal to find all views How does it work? @{dataBinding}
  19. layout/pet.xml generated: PetBinding.java PetBinding.image .title .upvote @{dataBinding}

  20. @{ }

  21. Existing attributes Pet.getName() app:title="@{pet.name}"

  22. android:text android:textColor Existing attributes android:drawableLeft android:src … and many, many

    more
  23. <Button app:selected=“@{vote == VOTE.UPVOTE}" android:tint=“@drawable/upvote_selector” /> Attributes for every Java

    setter View.setSelected()
  24. app:imageUrl="@{pet.imageUrl}" Custom attributes

  25. @BindingAdapter({"bind:imageUrl"}) public static void loadImage(ImageView view, String url) { Glide.with(view.getContext())

    .load(url) .into(view); } Bindings You pick The view you’re binding Attribute
  26. app:font Custom attributes @BindingAdapter({"bind:font"}) public static void setFont(TextView textView, String

    fontName) { Typeface type = FontCache.getInstance().get(fontName); textView.setTypeface(type); } Bindings Tinkerbell
  27. app:collapsedTitleTypeface="@{`LobsterTwo-Bold`}" app:expandedTitleTypeface="@{`LobsterTwo-Bold`}" Custom attributes @BindingAdapter("bind:expandedTitleTypeface") public static void setExpandedTitleTypeface( CollapsingToolbarLayout

    layout, String fontName) { Typeface type = FontCache.getInstance().get(fontName); layout.setExpandedTitleTypeface(type); } @BindingAdapter("bind:collapsedTitleTypeface") public static void setCollapsedTitleTypeface …
  28. <TextView android:drawableRight=“@{isCat ? @drawable/cat : @drawable/dog}” /> <View android:paddingRight=“@{2 *

    @dimen/margin}” /> <View android:paddingRight=“@{@dimen/margin + @dimen/image_width}” /> Evaluate simple expressions app:selected=“@{vote == VOTE.UPVOTE}"
  29. before: if (pet != null) { appBarLayout.setTitle(pet.getName()); } after: android:text=“@{pet.name}”

    Avoid NPEs android:text=“@{pet.name.last}”
  30. @BindingAdapter("android:indeterminateTint") public static void setIndeterminateTint( ProgressBar progressBar, int color) {

    Drawable toTint = progressBar.getIndeterminateDrawable().mutate(); toTint.setColorFilter(color, PorterDuff.Mode.SRC_IN); } Overwrite Android attributes <ProgressBar style="?android:attr/progressBarStyle" android:indeterminateTint="@{@color/pink}" />
  31. layout/family.xml <layout> … <include layout="@layout/pet" app:pet=“@{family.pet}" /> </layout> <include> layout/pet.xml

    <layout> <data> <variable name="pet" type="com.xwray.dogmeetscat.Pet"/> </data> … </layout>
  32. One way binding Model changes, view is updated Persistent binding

  33. enum VOTE { UPVOTE, DOWNVOTE, NONE } public class VoteState

    { public final ObservableField<VOTE> vote = new ObservableField(); } voteState.vote.set(VOTE.DOWNVOTE) Persistent binding
  34. enum VOTE { UPVOTE, DOWNVOTE, NONE } public class VoteState

    extends BaseObservable { private VOTE vote; @Bindable getVote(); setVote(VOTE vote) { this.vote = vote; notifyChanged(BR.vote) } } Persistent binding
  35. “In beta”, you said “It’ll be fun”, you said

  36. Gradle integration Syntax highlighting Code completion (2.0.0-alpha5) View and debug

    generated code Android Studio and You
  37. Refactoring “Convert to data binding” shortcut “Clean project” required sometimes

    Still to come …
  38. Android Studio tips <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> tools:text=“Jane Doe” tools:ignore="UnusedAttribute"

    Declare namespaces in layout tag Use tools: prefix for layout preview Ignore lint warnings
  39. app/build.gradle android { dataBinding { enabled = true } }

    How do I get started?
  40. fonts: goo.gl/n6lQY7 docs: goo.gl/47cVzB @lisawrayz