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

Bay Area Android: Yigit Boyar & George Mount: Data Binding in Android 6.0

1fa9cb8c7997c8c4d3d251fb5e41f749?s=47 Realm
September 23, 2015
87k

Bay Area Android: Yigit Boyar & George Mount: Data Binding in Android 6.0

1fa9cb8c7997c8c4d3d251fb5e41f749?s=128

Realm

September 23, 2015
Tweet

Transcript

  1. Android Data Binding Building Apps Faster George Mount Yigit Boyar

  2. Source: place source info here 2 Why Data Binding How

    Data Binding Works Data Binding Goodies Observability in Detail Performance RecyclerView / ListView and Data Binding Binding Adapters and Callbacks Best Practices 1 2 3 4 5 6 7 8
  3. 3 </LinearLayout> <LinearLayout …>
 <TextView android:id="@+id/name"/>

  4. 3 <TextView android:id="@+id/lastName"/> </LinearLayout> <LinearLayout …>
 <TextView android:id="@+id/name"/>

  5. private TextView mName
 protected void onCreate(Bundle savedInstanceState) {
 setContentView(R.layout.activity_main);
 mName

    = (TextView) findViewById(R.id.name);
 
 
 4 ; public void updateUI(User user) {
 if (user == null) {
 mName.setText(null); }
 } } else {
 } mName.setText(user.getName());
  6. private protected void setContentView(R.layout. mName 
 
 4 ; public

    void }
 } } else {
 }
  7. private protected void setContentView(R.layout. mName 
 
 4 ,mLastName ;

    public void }
 } } else {
 }
  8. private protected void setContentView(R.layout. mName 
 
 4 ,mLastName mLastName

    = (TextView) findViewById(R.id.lastName); ; public void }
 } } else {
 }
  9. private protected void setContentView(R.layout. mName 
 
 4 ,mLastName mLastName

    = (TextView) findViewById(R.id.lastName); mLastName.setText(null); ; public void }
 } } else {
 }
  10. private protected void setContentView(R.layout. mName 
 
 4 ,mLastName mLastName

    = (TextView) findViewById(R.id.lastName); mLastName.setText(null); mLastName.setText(user.getLastName()); ; public void }
 } } else {
 }
  11. private TextView mName
 protected void onCreate(Bundle savedInstanceState) {
 setContentView(R.layout.activity_main);
 mName

    = (TextView) findViewById(R.id.name);
 
 
 4 ,mLastName mLastName = (TextView) findViewById(R.id.lastName); mLastName.setText(null); mLastName.setText(user.getLastName()); ; public void updateUI(User user) {
 if (user == null) {
 mName.setText(null); }
 } } else {
 } mName.setText(user.getName());
  12. Source: place source info here 5 } public void updateUI(User

    user) {
 if (user == null) {
 mName.setText(null);
 mLastName.setText(null);
 } else {
 mName.setText(user.getName());
 mLastName.setText(user.getLastName());
 }
 } private
 private
 protected void onCreate(Bundle savedInstanceState) {
 setContentView(R.layout.activity_main);
 R.id.name R.id.lastName TextView mName; TextView mLastName; mName = (TextView) findViewById( );
 mLastName = (TextView) findViewById( );
  13. Source: place source info here 5 } public void }

    } } private private protected void setContentView(R.layout. R.id.name R.id.lastName TextView mName; TextView mLastName; mName = (TextView) findViewById( );
 mLastName = (TextView) findViewById( );
  14. Source: place source info here 5 } public void }

    } } private private protected void setContentView(R.layout. R.id.name R.id.lastName TextView mName; TextView mLastName; @Bind( ) @Bind( ) mName = (TextView) findViewById( );
 mLastName = (TextView) findViewById( );
  15. Source: place source info here 5 } public void }

    } } private private protected void setContentView(R.layout. R.id.name R.id.lastName TextView mName; TextView mLastName; @Bind( ) @Bind( ) ButterKnife.bind(this);
  16. Source: place source info here 5 } public void updateUI(User

    user) {
 if (user == null) {
 mName.setText(null);
 mLastName.setText(null);
 } else {
 mName.setText(user.getName());
 mLastName.setText(user.getLastName());
 }
 } private
 private
 protected void onCreate(Bundle savedInstanceState) {
 setContentView(R.layout.activity_main);
 R.id.name R.id.lastName TextView mName; TextView mLastName; @Bind( ) @Bind( ) ButterKnife.bind(this);
  17. 
 protected void onCreate(Bundle savedInstanceState) {
 setContentView(R.layout.activity_main);
 
 }
 public

    void updateUI(User user) {
 if (user == null) {
 
 } else {
 
 }
 } Source: place source info here 6 private @Bind(R.id.name) TextView name;
 private @Bind(R.id.lastName) TextView lastName; ButterKnife.bind(this); name.setText(null); lastName.setText(null); name.setText(user.getName()); lastName.setText(user.getLastName());
  18. 
 protected void setContentView(R.layout. 
 }
 public void if 


    } 
 } } Source: place source info here 6 private @Bind(R.id.name) TextView name;
 private @Bind(R.id.lastName) TextView lastName; ButterKnife.bind(this); name.setText(null); lastName.setText(null); name.setText(user.getName()); lastName.setText(user.getLastName());
  19. 
 protected void setContentView(R.layout. 
 }
 public void if 


    } 
 } } Source: place source info here 6 ButterKnife.bind(this); private Holdr_ActivityMain holder; name.setText(null); lastName.setText(null); name.setText(user.getName()); lastName.setText(user.getLastName());
  20. 
 protected void setContentView(R.layout. 
 }
 public void if 


    } 
 } } holder = new Holdr_ActivityMain(findViewById(content)); Source: place source info here 6 private Holdr_ActivityMain holder; name.setText(null); lastName.setText(null); name.setText(user.getName()); lastName.setText(user.getLastName());
  21. 
 protected void onCreate(Bundle savedInstanceState) {
 setContentView(R.layout.activity_main);
 
 }
 public

    void updateUI(User user) {
 if (user == null) {
 
 } else {
 
 }
 } holder = new Holdr_ActivityMain(findViewById(content)); Source: place source info here 6 private Holdr_ActivityMain holder; name.setText(null); lastName.setText(null); name.setText(user.getName()); lastName.setText(user.getLastName()); holder. holder. holder. holder.
  22. Source: place source info here private Holdr_ActivityMain holder;
 protected void

    onCreate(Bundle savedInstanceState) {
 setContentView(R.layout.activity_main);
 holder = new Holdr_ActivityMain(findViewById(content));
 }
 public void updateUI(User user) {
 if (user == null) {
 holder.name.setText(null);
 holder.lastName.setText(null);
 } else {
 holder.name.setText(user.getName());
 holder.lastName.setText(user.getLastName());
 }
 } 7
  23. Source: place source info here private Holdr_ActivityMain holder;
 protected void

    onCreate(Bundle savedInstanceState) {
 setContentView(R.layout.activity_main);
 holder = new Holdr_ActivityMain(findViewById(content));
 }
 public void updateUI(User user) {
 if (user == null) {
 holder.name.setText(null);
 holder.lastName.setText(null);
 } else {
 holder.name.setText(user.getName());
 holder.lastName.setText(user.getLastName());
 }
 } 7
  24. Source: place source info here 
 protected void onCreate(Bundle savedInstanceState)

    {
 }
 public void updateUI(User user) {
 
 8 private Holdr_ActivityMain mHolder; setContentView(R.layout.activity_main);
 mHolder = new Holdr_ActivityMain(findViewById(content)); if (user == null) {
 mHolder.name.setText(null);
 mHolder.lastName.setText(null);
 } else {
 mHolder.name.setText(user.getName());
 mHolder.lastName.setText(user.getLastName());
 } }
  25. Source: place source info here 
 protected void }
 public

    void 
 8 private Holdr_ActivityMain mHolder; setContentView(R.layout.activity_main);
 mHolder = new Holdr_ActivityMain(findViewById(content)); if (user == null) {
 mHolder.name.setText(null);
 mHolder.lastName.setText(null);
 } else {
 mHolder.name.setText(user.getName());
 mHolder.lastName.setText(user.getLastName());
 } }
  26. Source: place source info here 
 protected void }
 public

    void 
 8 setContentView(R.layout.activity_main);
 mHolder = new Holdr_ActivityMain(findViewById(content)); if (user == null) {
 mHolder.name.setText(null);
 mHolder.lastName.setText(null);
 } else {
 mHolder.name.setText(user.getName());
 mHolder.lastName.setText(user.getLastName());
 } private ActivityMainBinding mBinding; }
  27. Source: place source info here 
 protected void }
 public

    void 
 8 if (user == null) {
 mHolder.name.setText(null);
 mHolder.lastName.setText(null);
 } else {
 mHolder.name.setText(user.getName());
 mHolder.lastName.setText(user.getLastName());
 } mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); private ActivityMainBinding mBinding; }
  28. Source: place source info here 
 protected void }
 public

    void 
 8 mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); private ActivityMainBinding mBinding; mBinding.setUser(user); }
  29. Source: place source info here 
 protected void }
 public

    void 
 8 mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); private ActivityMainBinding mBinding; mBinding.setUser(user); }
  30. Source: place source info here 
 protected void onCreate(Bundle savedInstanceState)

    {
 }
 public void updateUI(User user) {
 
 8 mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); private ActivityMainBinding mBinding; mBinding.setUser(user); }
  31. Source: place source info here 9 <TextView android: /> <TextView

    android: /> <LinearLayout …> </LinearLayout> id="@+id/name" id="@+id/lastName"
  32. Source: place source info here 9 <TextView android: /> <TextView

    android: /> <LinearLayout …> </LinearLayout>
  33. Source: place source info here 9 <TextView android: /> <TextView

    android: /> <LinearLayout …> </LinearLayout> text="@{user.name}" text="@{user.lastName}"
  34. Source: place source info here 9 <TextView android: /> <TextView

    android: /> <LinearLayout …> </LinearLayout> text="@{user.name}" text="@{user.lastName}" ?
  35. Source: place source info here 9 <TextView android: /> <TextView

    android: /> <LinearLayout …> </LinearLayout> text="@{user.name}" text="@{user.lastName}" <layout>
 <data>
 <variable name=“user” type="com.android.example.User"/>
 </data> </layout>
  36. Source: place source info here 10 </LinearLayout> </layout> <TextView android:

    /> <TextView android: /> <LinearLayout …> text="@{user.lastName}" <layout>
 <data>
 <variable name=“user” type="com.android.example.User"/>
 </data> text="@{user.name}"
  37. Source: place source info here 10 </LinearLayout> </layout> <TextView android:

    /> <TextView android: /> <LinearLayout …> text="@{user.lastName}" <layout>
 <data>
 <variable name=“user” type="com.android.example.User"/>
 </data> text="@{user.name}" <TextView android:text=‘@{“” + user.age}’/>
  38. Source: place source info here 10 </LinearLayout> </layout> <TextView android:

    /> <TextView android: /> <LinearLayout …> text="@{user.lastName}" <layout>
 <data>
 <variable name=“user” type="com.android.example.User"/>
 </data> text="@{user.name}" <TextView android:text=‘@{“” + user.age}’/>
  39. Source: place source info here 11 Why Data Binding How

    Data Binding Works Data Binding Goodies Observability in Detail Performance RecyclerView / ListView and Data Binding Binding Adapters and Callbacks Best Practices 2 1 3 4 5 6 7 8
  40. Source: place source info here What is happening ? 12

  41. Source: place source info here What is happening ? 12

    Process Layout Files
  42. Source: place source info here What is happening ? 12

    Process Layout Files <TextView /> android:visibility=“@{user.isAdmin ? View.VISIBLE : View.GONE}”
  43. Source: place source info here What is happening ? 12

    Process Layout Files <TextView />
  44. user.isAdmin ? View.VISIBLE : View.GONE Source: place source info here

    What is happening ? 12 Process Layout Files Parse Expressions
  45. user.isAdmin ? View.VISIBLE : View.GONE Source: place source info here

    What is happening ? 12 Process Layout Files Parse Expressions
  46. user.isAdmin ? View.VISIBLE : View.GONE Source: place source info here

    What is happening ? 12 Process Layout Files Parse Expressions ID ID ID
  47. user.isAdmin ? View.VISIBLE : View.GONE Source: place source info here

    What is happening ? 12 Process Layout Files Parse Expressions ID field access field access ID ID field access
  48. user.isAdmin ? View.VISIBLE : View.GONE Source: place source info here

    What is happening ? 12 Process Layout Files Parse Expressions ID field access field access Ternary ID ID field access
  49. Source: place source info here What is happening ? 12

    Process Layout Files Parse Expressions Resolve Dependencies
  50. Source: place source info here What is happening ? 12

    Process Layout Files Parse Expressions Resolve Dependencies user.isAdmin
  51. Source: place source info here What is happening ? 12

    Process Layout Files Parse Expressions Resolve Dependencies user.isAdmin variable
  52. Source: place source info here What is happening ? 12

    Process Layout Files Parse Expressions Resolve Dependencies user.isAdmin variable boolean isAdmin()
  53. Source: place source info here What is happening ? 12

    Process Layout Files Parse Expressions Resolve Dependencies user.isAdmin variable boolean isAdmin() boolean
  54. Source: place source info here What is happening ? 12

    Process Layout Files Parse Expressions Resolve Dependencies
  55. Source: place source info here What is happening ? 12

    Process Layout Files Parse Expressions Resolve Dependencies Write Data Binders
  56. Source: place source info here What is happening ? 12

    Process Layout Files Parse Expressions Resolve Dependencies Write Data Binders
  57. <RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"/>
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"/>
 </RelativeLayout>


    Source: place source info here 13 <layout >
 <data>
 <variable name="user" type="com.android.example.User"/>
 </data>
 </layout>
 xmlns:android="http://schemas.android.com/apk/res/android" android:text="@{user.name}" android:text="@{user.lastname}"
  58. <RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"/>
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"/>
 </RelativeLayout>


    Source: place source info here 13 xmlns:android="http://schemas.android.com/apk/res/ android:text="@{user.name}" android:text="@{user.lastname}"
  59. <RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"/>
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"/>
 </RelativeLayout>


    Source: place source info here 13 xmlns:android="http://schemas.android.com/apk/res/
  60. <RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"/>
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"/>
 </RelativeLayout>


    Source: place source info here 13 xmlns:android="http://schemas.android.com/apk/res/ android:tag="binding_1" android:tag="binding_2"
  61. Source: place source info here 14 <TextView android:text=“@{ }"/> user.age

    < 18 ? @string/redacted user.name :
  62. Source: place source info here 14 <TextView android:text=“@{ }"/> user.age

    < 18 ? @string/redacted user.name :
  63. Source: place source info here 14 <TextView android:text=“@{ }"/> user

    . age < 18 ? @string/redacted user . name :
  64. Source: place source info here 14 <TextView android:text=“@{ }"/> user

    . age < 18 ? @string/redacted user . name : User int User String
  65. Source: place source info here 14 <TextView android:text=“@{ }"/> user

    . age < 18 ? @string/redacted user . name : User getAge() int User String
  66. Source: place source info here 14 <TextView android:text=“@{ }"/> user

    . age < 18 ? @string/redacted user . name : User getAge() int int boolean User String
  67. Source: place source info here 14 <TextView android:text=“@{ }"/> user

    . age < 18 ? @string/redacted user . name : User getAge() int int boolean User getName() String
  68. Source: place source info here 14 <TextView android:text=“@{ }"/> user

    . age < 18 ? @string/redacted user . name : User getAge() int int boolean User getName() String String
  69. Source: place source info here 14 <TextView android:text=“@{ }"/> user

    . age < 18 ? @string/redacted user . name : User getAge() int int boolean User getName() String String String
  70. Source: place source info here 14 <TextView android:text=“@{ }"/> user

    . age < 18 ? @string/redacted user . name : User getAge() int int boolean User getName() String String String
  71. Source: place source info here 14 <TextView android:text=“@{ }"/> user

    . age < 18 ? @string/redacted user . name : User getAge() int int boolean User getName() String String String setText(CharSequence)
  72. Source: place source info here Resolving Setters 15

  73. Source: place source info here Resolving Setters 15 <TextView android:text="@{myVariable}"/>

  74. Source: place source info here Resolving Setters 15 <TextView android:text="@{myVariable}"/>

    textView.setText(myVariable);
  75. Source: place source info here Resolving Setters 15 <TextView textView.setText(myVariable);

    <ImageView android:src="@{user.image}"/>
  76. Source: place source info here Resolving Setters 15 <TextView textView.setText(myVariable);

    <ImageView android:src="@{user.image}"/> imageView.setSrc(user.image);
  77. Source: place source info here Resolving Setters 15 <TextView textView.setText(myVariable);

    <ImageView android:src="@{user.image}"/> imageView.setSrc(user.image);
  78. imageView.setImageResource(user.image); Source: place source info here Resolving Setters 15 <TextView

    textView.setText(myVariable); <ImageView android:src="@{user.image}"/>
  79. imageView.setImageResource(user.image); Source: place source info here Resolving Setters 15 <TextView

    textView.setText(myVariable); <ImageView android:src="@{user.image}"/> @BindingMethod(
 type = android.widget.ImageView.class,
 attribute = "android:src",
 method = "setImageResource")
  80. Source: place source info here 16 Why Data Binding How

    Data Binding Works Data Binding Goodies Observability in Detail Performance RecyclerView / ListView and Data Binding Binding Adapters and Callbacks Best Practices 3 1 2 4 5 6 7 8
  81. 17 Goodies

  82. Expression language is mostly Java 18

  83. obj.name Expression language is mostly Java 18

  84. obj. Expression language is mostly Java 18 obj.name.length()

  85. obj. Expression language is mostly Java 18 obj. obj.name.charAt(0)  

  86. obj. Expression language is mostly Java 18 obj. obj.age  +

     18   obj.
  87. obj. Expression language is mostly Java 18 obj. obj. obj.age

     >  18   obj.
  88. obj. Expression language is mostly Java 18 obj. obj. obj.

    obj. obj.friends[selectedIndex]
  89. obj. Expression language is mostly Java 18 obj. obj. View.VISIBLE

      obj. obj. obj.
  90. obj. Expression language is mostly Java 18 obj. obj. View.VISIBLE

    obj. obj. obj. obj.admin  ?  View.VISIBLE  :  View.GONE  
  91. Short and readable 19

  92. Short and readable 19 Fields access shortcut contact.name   public

     String  name;   public  String  getName()  {…}   public  boolean  isName()  {…}   public  String  name()  {…}
  93. Short and readable 19 Automatic null check contact.friend.name Fields access

    shortcut contact.name   public  String  name;   public  String  getName()  {…}   public  boolean  isName()  {…}   public  String  name()  {…}
  94. Short and readable 19 Null coalescing operator contact.lastName  ??  contact.name

      contact.lastName  !=  null  ?  contact.lastName  :  contact.name Automatic null check contact.friend.name Fields access shortcut contact.name   public  String  name;   public  String  getName()  {…}   public  boolean  isName()  {…}   public  String  name()  {…}
  95. Short and readable 19 List & Map Access contacts[0]  

    contactInfo["firstName"] Null coalescing operator contact.lastName  ??  contact.name   contact.lastName  !=  null  ?  contact.lastName  :  contact.name Automatic null check contact.friend.name Fields access shortcut contact.name   public  String  name;   public  String  getName()  {…}   public  boolean  isName()  {…}   public  String  name()  {…}
  96. Resources 20

  97. Resources In Expressions android:padding="@{isBig  ?  @dimen/bigPadding  :  @dimen/smallPadding}" 20

  98. Resources In Expressions android:padding="@{isBig  ?  @dimen/bigPadding  :  @dimen/smallPadding}" Inline string

    formatting android:text="@{@string/nameFormat(firstName,  lastName)}" 20
  99. Resources In Expressions android:padding="@{isBig  ?  @dimen/bigPadding  :  @dimen/smallPadding}"   Inline

    string formatting android:text="@{@string/nameFormat(firstName,  lastName)}"   Inline plurals android:text="@{@plurals/banana(bananaCount)}" 20
  100. Resources 20

  101. Automagic Attributes 21

  102. Automagic Attributes 
 <android.support.v4.widget.DrawerLayout
        android:layout_width="wrap_content"
    

       android:layout_height="wrap_content"
        app:scrimColor="@{@color/scrim}"/>
 drawerLayout.setScrimColor(
      resources.getColor(R.color.scrim)) 21
  103. Automagic Attributes 21

  104. Event Handlers 
 22

  105. Event Handlers 
 22 <Button  android:onClick="clicked"  …/>


  106. Event Handlers 
 22 <Button  android:onClick="clicked"  …/>
 
 <Button  android:onClick="@{handlers.clicked}"

     …/>
  107. Event Handlers 
 22 <Button  android:onClick="clicked"  …/>
 
 <Button  android:onClick="@{handlers.clicked}"

     …/> 
 
 <Button  android:onClick="@{isAdult  ?  handlers.adultClick  :   handlers.childClick}"  …/>
  108. Event Handlers 
 22 <Button  android:onClick="clicked"  …/>
 
 <Button  android:onClick="@{handlers.clicked}"

     …/>   
 
 <Button  android:onClick="@{isAdult  ?  handlers.adultClick  :   handlers.childClick}"  …/>   
 
 <Button  android:onTextChanged="@{handlers.textChanged}"  …/>
  109. Event Handlers 
 22

  110. Source: place source info here 23 Why Data Binding How

    Data Binding Works Data Binding Goodies Observability in Detail Performance RecyclerView / ListView and Data Binding Binding Adapters and Callbacks Best Practices 4 1 3 2 5 6 7 8
  111. 24 Change

  112. 25 Image: pink_droid Price: $20.06

  113. 25 Image: pink_droid Price: $20.06 Image: pink_droid Price: $33.41

  114. 25 Image: pink_droid Price: $20.06 Image: pink_droid Price: $33.41 $33.41

  115. 25 Image: pink_droid Price: $20.06

  116. 26 Image: pink_droid Price: $20.06

  117. 26 Image: pink_droid Price: $20.06 public  class  Item  extends  BaseObservable

     {
        private  String  price;
 
        @Bindable
        public  String  getPrice()  {
                return  this.name;
        }
 
        public  void  setPrice(String  price)  {
                this.price  =  price;
                notifyPropertyChanged(BR.price);
        }
 }
  118. 26 Image: pink_droid Price: $20.06 public  class  Item  extends  BaseObservable

     {
        private  String  price;
 
        @Bindable
        public  String  getPrice()  {
                return  this.name;
        }
 
        public  void  setPrice(String  price)  {
                this.price  =  price;
                notifyPropertyChanged(BR.price);
        }
 }
  119. 26 Image: pink_droid Price: $20.06 public  class  Item  extends  BaseObservable

     {
        private  String  price;
 
        @Bindable
        public  String  getPrice()  {
                return  this.name;
        }
 
        public  void  setPrice(String  price)  {
                this.price  =  price;
                notifyPropertyChanged(BR.price);
        }
 }
  120. 26 Image: pink_droid Price: $20.06 public  class  Item  extends  BaseObservable

     {
        private  String  price;
 
        @Bindable
        public  String  getPrice()  {
                return  this.name;
        }
 
        public  void  setPrice(String  price)  {
                this.price  =  price;
                notifyPropertyChanged(BR.price);
        }
 }
  121. 26 Image: pink_droid Price: $20.06

  122. 27 Image: pink_droid Price: $20.06

  123. 27 Image: pink_droid Price: $20.06 public  class  Item  implements  Observable

     {
        private  PropertyChangeRegistry  callbacks  =  new  …
        …
        @Override
        public  void  addOnPropertyChangedCallback(                          OnPropertyChangedCallback  callback)  {
                callbacks.add(callback);
        }
        @Override
        public  void  removeOnPropertyChangedCallback(                          OnPropertyChangedCallback  callback)  {
                callbacks.remove(callback);
        }
 }
  124. 27 Image: pink_droid Price: $20.06

  125. 28 Image: pink_droid Price: $20.06

  126. 28 Image: pink_droid Price: $20.06 public  class  Item  {
  

         public  final  ObservableField<Drawable>  image  =
                        new  ObservableField<>();
        public  final  ObservableField<String>  price  =
                        new  ObservableField<>();
        public  final  ObservableInt  inventory  =
                        new  ObservableInt();
 }
 
 item.price.set("$33.41");
  127. 28 Image: pink_droid Price: $20.06 public  class  Item  {
  

         public  final  ObservableField<Drawable>  image  =
                        new  ObservableField<>();
        public  final  ObservableField<String>  price  =
                        new  ObservableField<>();
        public  final  ObservableInt  inventory  =
                        new  ObservableInt();
 }
 
 item.price.set("$33.41");
  128. 28 Image: pink_droid Price: $20.06

  129. 29 Image: pink_droid Price: $20.06

  130. 29 Image: pink_droid Price: $20.06 ObservableMap<String,  Object>  item  =
  

                 new  ObservableArrayMap<>();
 item.put("price",  "$33.41");   <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"  
        android:text='@{item["price"]}'/>

  131. 29 Image: pink_droid Price: $20.06 ObservableMap<String,  Object>  item  =
  

                 new  ObservableArrayMap<>();
 item.put("price",  "$33.41");   <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"  
        android:text='@{item["price"]}'/>

  132. 29 Image: pink_droid Price: $20.06

  133. Photo by Chet Haase Notify on any thread • UI

    updates scheduled for next frame • Data read on UI thread • Only remove items from lists on the UI thread! 30
  134. Photo by Chet Haase Notify on any thread • UI

    updates scheduled for next frame • Data read on UI thread • Only remove items from lists on the UI thread! 30
  135. Source: place source info here 31 Why Data Binding How

    Data Binding Works Data Binding Goodies Observability in Detail Performance RecyclerView / ListView and Data Binding Binding Adapters and Callbacks Best Practices 5 1 3 2 4 6 7 8
  136. Source: place source info here 32 No reflection

  137. Source: place source info here 33

  138. Source: place source info here 33

  139. Source: place source info here 33

  140. Source: place source info here 34 <TextView android:text="@{user.address.street}"/>
 <TextView android:text="@{user.address.city}"/>

  141. Source: place source info here 34 <TextView android:text="@{user.address.street}"/>
 <TextView android:text="@{user.address.city}"/>

  142. Source: place source info here 34 <TextView android:text="@{user.address.street}"/>
 <TextView android:text="@{user.address.city}"/>

    Address address = user.getAddress(); String street = address.getStreet(); String city = address.getCity();
  143. Source: place source info here findViewById Traversal 35

  144. Source: place source info here findViewById Traversal 35 view.findViewById(…)

  145. Source: place source info here findViewById Traversal 35 view.findViewById(…) children[0].findViewById(…)

  146. Source: place source info here findViewById Traversal 35 view.findViewById(…) children[0].findViewById(…)

    children[1].findViewById(…)
  147. Source: place source info here findViewById Traversal 35 view.findViewById(…) children[0].findViewById(…)

    children[1].findViewById(…)
  148. Source: place source info here findViewById Traversal 35 view.findViewById(…) children[0].findViewById(…)

    children[1].findViewById(…)
  149. Source: place source info here One Pass View Collection 36

  150. Source: place source info here One Pass View Collection 36

    findAllViews(root, View[])
  151. Source: place source info here One Pass View Collection 36

    findAllViews(root, View[]) findAllViews(child[0], View[])
  152. Source: place source info here One Pass View Collection 36

    findAllViews(root, View[]) findAllViews(child[0], View[]) findAllViews(child[0], View[])
  153. Source: place source info here One Pass View Collection 36

    findAllViews(root, View[]) findAllViews(child[0], View[]) findAllViews(child[0], View[])
  154. Source: place source info here One Pass View Collection 36

    findAllViews(root, View[]) findAllViews(child[0], View[]) findAllViews(child[0], View[]) NO SECOND PASS
  155. Source: place source info here 37 Why Data Binding How

    Data Binding Works Data Binding Goodies Observability in Detail Performance RecyclerView / ListView and Data Binding Binding Adapters and Callbacks Best Practices 6 1 3 2 4 5 7 8
  156. public class UserViewHolder extends RecyclerView.ViewHolder {
 
 
 } Source:

    place source info here 38
  157. public class UserViewHolder extends RecyclerView.ViewHolder {
 
 
 } static

    UserViewHolder create(LayoutInflater inflater, ViewGroup parent) { UserItemBinding binding = UserItemBinding .inflate(inflater, parent, false); return new UserViewHolder(binding); } Source: place source info here 38
  158. public class UserViewHolder extends RecyclerView.ViewHolder {
 
 
 } static

    UserViewHolder create(LayoutInflater inflater, ViewGroup parent) { UserItemBinding binding = UserItemBinding .inflate(inflater, parent, false); return new UserViewHolder(binding); } Source: place source info here 38 private UserItemBinding mBinding; private UserViewHolder(UserItemBinding binding) { super(binding.getRoot()); mBinding = binding; }
  159. public class UserViewHolder extends RecyclerView.ViewHolder {
 
 
 } static

    UserViewHolder create(LayoutInflater inflater, ViewGroup parent) { UserItemBinding binding = UserItemBinding .inflate(inflater, parent, false); return new UserViewHolder(binding); } Source: place source info here 38 private UserItemBinding mBinding; private UserViewHolder(UserItemBinding binding) { super(binding.getRoot()); mBinding = binding; } public void bindTo(User user) { mBinding.setUser(user); mBinding.executePendingBindings(); }
  160. public class UserViewHolder extends RecyclerView.ViewHolder {
 
 
 } static

    UserViewHolder create(LayoutInflater inflater, ViewGroup parent) { UserItemBinding binding = UserItemBinding .inflate(inflater, parent, false); return new UserViewHolder(binding); } Source: place source info here 38 private UserItemBinding mBinding; private UserViewHolder(UserItemBinding binding) { super(binding.getRoot()); mBinding = binding; } public void bindTo(User user) { mBinding.setUser(user); mBinding.executePendingBindings(); }
  161. Source: place source info here 39 public UserViewHolder onCreateViewHolder(ViewGroup viewGroup,

    int i) {
 return UserViewHolder.create(mLayoutInflater, viewGroup);
 }
 
 public void onBindViewHolder(UserViewHolder userViewHolder, int position) {
 userViewHolder.bindTo(mUserList.get(position));
 }
  162. Source: place source info here What happens when user is

    updated? 40 user.notifyPropertyChanged(BR.name);
  163. Source: place source info here What happens when user is

    updated? 40 user.notifyPropertyChanged(BR.name); binding.requestRebind();
  164. Source: place source info here What happens when user is

    updated? 40 user.notifyPropertyChanged(BR.name); binding.requestRebind(); textView.setText(user.name);
  165. Source: place source info here What happens when user is

    updated? 40 user.notifyPropertyChanged(BR.name); binding.requestRebind(); textView.setText(user.name); textView.requestLayout();
  166. Source: place source info here What happens when user is

    updated? 40 user.notifyPropertyChanged(BR.name); binding.requestRebind(); textView.setText(user.name); textView.requestLayout(); recyclerView.onLayout(…);
  167. Source: place source info here What happens when user is

    updated? 40 user.notifyPropertyChanged(BR.name); binding.requestRebind(); textView.setText(user.name); textView.requestLayout(); recyclerView.onLayout(…); NO ANIMATIONS!
  168. Source: place source info here What we want it to

    happen? 41 user.notifyPropertyChanged(BR.name);
  169. Source: place source info here What we want it to

    happen? 41 user.notifyPropertyChanged(BR.name); adapter.notifyItemChanged(…);
  170. Source: place source info here What we want it to

    happen? 41 user.notifyPropertyChanged(BR.name); adapter.notifyItemChanged(…); recyclerView.onLayout(…);
  171. Source: place source info here What we want it to

    happen? 41 user.notifyPropertyChanged(BR.name); adapter.notifyItemChanged(…); adapter.onBind(…); recyclerView.onLayout(…);
  172. Source: place source info here What we want it to

    happen? 41 user.notifyPropertyChanged(BR.name); textView.setText(user.name); adapter.notifyItemChanged(…); adapter.onBind(…); recyclerView.onLayout(…);
  173. Source: place source info here What we want it to

    happen? 41 user.notifyPropertyChanged(BR.name); textView.setText(user.name); adapter.notifyItemChanged(…); adapter.onBind(…); recyclerView.onLayout(…); MUCHO ANIMATIONS!
  174. Source: place source info here 42 public UserViewHolder onCreateViewHolder(ViewGroup viewGroup,

    int i) {
 final UserViewHolder holder = UserViewHolder.create(mLayoutInflater, viewGroup);
 
 
 
 return holder;
 }
  175. holder.getBinding().addOnRebindCallback(new OnRebindCallback() { }); Source: place source info here 42

    public UserViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
 final UserViewHolder holder = UserViewHolder.create(mLayoutInflater, viewGroup);
 
 
 
 return holder;
 }
  176. holder.getBinding().addOnRebindCallback(new OnRebindCallback() { }); Source: place source info here 42

    public UserViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
 final UserViewHolder holder = UserViewHolder.create(mLayoutInflater, viewGroup);
 
 
 
 return holder;
 } public boolean onPreBind(ViewDataBinding binding) { }
  177. holder.getBinding().addOnRebindCallback(new OnRebindCallback() { }); Source: place source info here 42

    public UserViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
 final UserViewHolder holder = UserViewHolder.create(mLayoutInflater, viewGroup);
 
 
 
 return holder;
 } public boolean onPreBind(ViewDataBinding binding) { } public void onCanceled(ViewDataBinding binding) { }
  178. holder.getBinding().addOnRebindCallback(new OnRebindCallback() { }); Source: place source info here 42

    public UserViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
 final UserViewHolder holder = UserViewHolder.create(mLayoutInflater, viewGroup);
 
 
 
 return holder;
 } public boolean onPreBind(ViewDataBinding binding) { } public void onCanceled(ViewDataBinding binding) { } return mRecyclerView != null && mRecyclerView.isComputingLayout();
  179. holder.getBinding().addOnRebindCallback(new OnRebindCallback() { }); Source: place source info here 42

    public UserViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
 final UserViewHolder holder = UserViewHolder.create(mLayoutInflater, viewGroup);
 
 
 
 return holder;
 } public boolean onPreBind(ViewDataBinding binding) { } public void onCanceled(ViewDataBinding binding) { } return mRecyclerView != null && mRecyclerView.isComputingLayout(); if (mRecyclerView == null || mRecyclerView.isComputingLayout()) { return; } int position = holder.getAdapterPosition(); if (position != RecyclerView.NO_POSITION) { notifyItemChanged(position, DATA_INVALIDATION); }
  180. holder.getBinding().addOnRebindCallback(new OnRebindCallback() { }); Source: place source info here 42

    public UserViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
 final UserViewHolder holder = UserViewHolder.create(mLayoutInflater, viewGroup);
 
 
 
 return holder;
 } public boolean onPreBind(ViewDataBinding binding) { } public void onCanceled(ViewDataBinding binding) { } return mRecyclerView != null && mRecyclerView.isComputingLayout(); if (mRecyclerView == null || mRecyclerView.isComputingLayout()) { return; } int position = holder.getAdapterPosition(); if (position != RecyclerView.NO_POSITION) { notifyItemChanged(position, DATA_INVALIDATION); }
  181. holder.getBinding().addOnRebindCallback(new OnRebindCallback() { }); Source: place source info here 42

    public UserViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
 final UserViewHolder holder = UserViewHolder.create(mLayoutInflater, viewGroup);
 
 
 
 return holder;
 } public boolean onPreBind(ViewDataBinding binding) { } public void onCanceled(ViewDataBinding binding) { } return mRecyclerView != null && mRecyclerView.isComputingLayout(); if (mRecyclerView == null || mRecyclerView.isComputingLayout()) { return; } int position = holder.getAdapterPosition(); if (position != RecyclerView.NO_POSITION) { notifyItemChanged(position, DATA_INVALIDATION); } PAYLOAD
  182. Source: place source info here 43 public void onBindViewHolder(UserViewHolder userViewHolder,

    int position) {
 userViewHolder.bindTo(mUserList.get(position));
 }
  183. Source: place source info here 43 public void onBindViewHolder(UserViewHolder userViewHolder,

    int position) {
 userViewHolder.bindTo(mUserList.get(position));
 } public void onBindViewHolder(UserViewHolder holder, int position, List<Object> payloads) { }
  184. Source: place source info here 43 public void onBindViewHolder(UserViewHolder userViewHolder,

    int position) {
 userViewHolder.bindTo(mUserList.get(position));
 } public void onBindViewHolder(UserViewHolder holder, int position, List<Object> payloads) { } notifyItemChanged(position, DATA_INVALIDATION);
  185. Source: place source info here 43 public void onBindViewHolder(UserViewHolder userViewHolder,

    int position) {
 userViewHolder.bindTo(mUserList.get(position));
 } public void onBindViewHolder(UserViewHolder holder, int position, List<Object> payloads) { }
  186. Source: place source info here 43 public void onBindViewHolder(UserViewHolder userViewHolder,

    int position) {
 userViewHolder.bindTo(mUserList.get(position));
 } public void onBindViewHolder(UserViewHolder holder, int position, List<Object> payloads) { } if (isForDataBinding(payloads)) { holder.getBinding().executePendingBindings(); } else { onBindViewHolder(holder, position); }
  187. Source: place source info here 44 private boolean isForDataBinding(List<Object> payloads)

    {
 
 }
  188. Source: place source info here 44 private boolean isForDataBinding(List<Object> payloads)

    {
 
 } if (payloads == null || payloads.size() == 0) { return false; } for (Object obj : payloads) { if (obj != DATA_INVALIDATION) { return false; } } return true;
  189. Source: place source info here 44 private boolean isForDataBinding(List<Object> payloads)

    {
 
 } static Object DATA_INVALIDATION = new Object(); if (payloads == null || payloads.size() == 0) { return false; } for (Object obj : payloads) { if (obj != DATA_INVALIDATION) { return false; } } return true;
  190. <layout>
 <data>
 <variable name="data" type=“com.example. "/>
 </data>
 
 Multiple View

    Types 45 </layout> Photo <ImageView android:src=“@{data.url}" …/>
  191. <layout < < </ 
 Multiple View Types 45 </

    Photo <ImageView android:src=“@{data.url}" …/>
  192. <layout < < </ 
 Multiple View Types 45 </

    <ImageView android:src=“@{data.url}" …/>
  193. <layout < < </ 
 Multiple View Types 45 </

    Place <ImageView android:src=“@{data.url}" …/>
  194. <layout < < </ 
 Multiple View Types 45 </

    Place <TextView android:text=“@{data.name}" …/> <ImageView android:src="@{data.isFav ? @drawable/active : @drawable/passive}”
  195. <layout>
 <data>
 <variable name="data" type=“com.example. "/>
 </data>
 
 Multiple View

    Types 45 </ Place <TextView android:text=“@{data.name}" …/> <ImageView android:src="@{data.isFav ? @drawable/active : @drawable/passive}”
  196. Source: place source info here 46

  197. Source: place source info here public class DataBoundViewHolder extends RecyclerView.ViewHolder

    {
 
 
 } 46
  198. Source: place source info here public class 
 
 }

    46 private ViewDataBinding mBinding;
  199. Source: place source info here public class 
 
 }

    46 private public DataBoundViewHolder(ViewDataBinding binding) {
 super(binding.getRoot());
 mBinding = binding;
 }
  200. Source: place source info here public class 
 
 }

    46 private public } public ViewDataBinding getBinding() { return mBinding; }
  201. Source: place source info here public class 
 
 }

    46 private public } public ViewDataBinding getBinding() { return mBinding; } public void bindTo( ) { mBinding mBinding.executePendingBindings(); } .setPlace(place); Place place
  202. Source: place source info here public class 
 
 }

    46 private public } public ViewDataBinding getBinding() { return mBinding; } public void bindTo( ) { mBinding mBinding.executePendingBindings(); } METHOD DOES NOT EXIST! .setPlace(place); Place place
  203. Source: place source info here public class 
 
 }

    46 private public } public ViewDataBinding getBinding() { return mBinding; } public void bindTo( ) { mBinding mBinding.executePendingBindings(); }
  204. .setVariable(BR.data, obj); Object obj Source: place source info here public

    class 
 
 } 46 private public } public ViewDataBinding getBinding() { return mBinding; } public void bindTo( ) { mBinding mBinding.executePendingBindings(); }
  205. .setVariable(BR.data, obj); Object obj Source: place source info here public

    class DataBoundViewHolder extends RecyclerView.ViewHolder {
 
 
 } 46 private ViewDataBinding mBinding; public DataBoundViewHolder(ViewDataBinding binding) {
 super(binding.getRoot());
 mBinding = binding;
 } public ViewDataBinding getBinding() { return mBinding; } public void bindTo( ) { mBinding mBinding.executePendingBindings(); } boolean setVariable(int id, Object obj) { if (id == BR.data) { setPhoto((Photo) obj); return true; } return false; }
  206. 47 DataBoundViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
 return DataBoundViewHolder.create(mLayoutInflater, viewGroup,

    type);
 }
 
 void onBindViewHolder(DataBoundViewHolder viewHolder, int position) {
 viewHolder.bindTo(mDataList.get(position));
 }
  207. 47 DataBoundViewHolder onCreateViewHolder(ViewGroup viewGroup, return }
 
 void viewHolder.bindTo( }

  208. 47 DataBoundViewHolder onCreateViewHolder(ViewGroup viewGroup, return }
 
 void viewHolder.bindTo( }

    public int getItemViewType(int position) { Object item = mItems.get(position);
 
 }
  209. 47 DataBoundViewHolder onCreateViewHolder(ViewGroup viewGroup, return }
 
 void viewHolder.bindTo( }

    public int Object item = 
 } if (item instanceof Place) { return R.layout.place_layout; } else if (item instanceof Photo) { return R.layout.photo_layout; } throw new RuntimeException("invalid obj");
  210. 47 DataBoundViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
 return DataBoundViewHolder.create(mLayoutInflater, viewGroup,

    type);
 }
 
 void onBindViewHolder(DataBoundViewHolder viewHolder, int position) {
 viewHolder.bindTo(mDataList.get(position));
 } public int getItemViewType(int position) { Object item = mItems.get(position);
 
 } if (item instanceof Place) { return R.layout.place_layout; } else if (item instanceof Photo) { return R.layout.photo_layout; } throw new RuntimeException("invalid obj");
  211. Source: place source info here 48 Why Data Binding How

    Data Binding Works Data Binding Goodies Observability in Detail Performance RecyclerView / ListView and Data Binding Binding Adapters and Callbacks Best Practices 7 2 3 4 5 6 1 8
  212. 49 Binding Adapters

  213. Something a bit more complex than setText
 50

  214. Something a bit more complex than setText
 50 <ImageView  …


           android:src="@{contact.largeImageUrl}"  />
  215. Something a bit more complex than setText
 50 <ImageView  …


           android:src="@{contact.largeImageUrl}"  />   
 
 
 
 @BindingAdapter("android:src")
 public  static  void  setImageUrl(ImageView  view,  String  url)  {
        Picasso.with(view.getContext()).load(url).into(view);
 }
  216. Something a bit more complex than setText
 50

  217. Attributes working together
 51

  218. Attributes working together
 51 <ImageView  …
      android:src="@{contact.largeImageUrl}"
  

       app:placeHolder=“@{R.drawable.contact_placeholder}"/>
  219. Attributes working together
 51 <ImageView  …
      android:src="@{contact.largeImageUrl}"
  

       app:placeHolder=“@{R.drawable.contact_placeholder}"/>   
 @BindingAdapter(value  =  {"android:src",  "placeHolder"},
                                requireAll  =  false)
 public  static  void  setImageUrl(ImageView  view,  String  url,
                                                              int  placeHolder)  {
        RequestCreator  requestCreator  =
                Picasso.with(view.getContext()).load(url);
        if  (placeHolder  !=  0)  {
                requestCreator.placeholder(placeHolder);
        }
        requestCreator.into(view);
 }
  220. Attributes working together
 51

  221. Using Previous Values
 52

  222. Using Previous Values
 52 @BindingAdapter("android:onLayoutChange")
 public  static  void  setOnLayoutChangeListener(View  view,


                   View.OnLayoutChangeListener  oldValue,
                View.OnLayoutChangeListener  newValue)  {
        if  (Build.VERSION.SDK_INT  >=  Build.VERSION_CODES.HONEYCOMB)  {
                if  (oldValue  !=  null)  {
                        view.removeOnLayoutChangeListener(oldValue);
                }
                if  (newValue  !=  null)  {
                        view.addOnLayoutChangeListener(newValue);
                }
        }
 }
  223. Using Previous Values
 52

  224. Dependency Injection
 53

  225. Dependency Injection
 53 public  interface  TestableAdapter  {
      

     @BindingAdapter("android:src")
        void  setImageUrl(ImageView  imageView,  String  url);
 }

  226. Dependency Injection
 53 public  interface  TestableAdapter  {
      

     @BindingAdapter("android:src")
        void  setImageUrl(ImageView  imageView,  String  url);
 }
 public  interface  DataBindingComponent  {
        TestableAdapter  getTestableAdapter();
 }

  227. Dependency Injection
 53 public  interface  TestableAdapter  {
      

     @BindingAdapter("android:src")
        void  setImageUrl(ImageView  imageView,  String  url);
 }
 public  interface  DataBindingComponent  {
        TestableAdapter  getTestableAdapter();
 }
 DataBindingUtil.setDefaultComponent(myComponent);
  228. Dependency Injection
 53 public  interface  TestableAdapter  {
      

     @BindingAdapter("android:src")
        void  setImageUrl(ImageView  imageView,  String  url);
 }
 public  interface  DataBindingComponent  {
        TestableAdapter  getTestableAdapter();
 }
 DataBindingUtil.setDefaultComponent(myComponent);    -­‐  or  -­‐
 binding  =  MyLayoutBinding.inflate(layoutInflater,  myComponent);
  229. Dependency Injection
 53

  230. Component For Context 
 54

  231. Component For Context 
 54 @BindingAdapter("android:src")
 public  static  void  setImageUrl(MyAppComponent

     component,                                                                ImageView  view,                                                                String  imageUrl)  {
        component.getImageCache().loadInto(view,  imageUrl);
 }
  232. Component For Context 
 54

  233. Event Handlers 
 55

  234. Event Handlers 
 55 <Button  …
  android:onClick=“@{isAdmin  ?  handler.adminClick  :

     handler.userClick}”  />

  235. Event Handlers 
 55 <Button  …
  android:onClick=“@{isAdmin  ?  handler.adminClick  :

     handler.userClick}”  />
 No “setOnClick” method for View. Need a way to find it. @BindingMethods({
        @BindingMethod(type  =  View.class,
                                      attribute  =  “android:onClick",
                                      method  =  “setOnClickListener"})
  236. Event Handlers 
 55 <Button  …
  android:onClick=“@{isAdmin  ?  handler.adminClick  :

     handler.userClick}”  />
 No “setOnClick” method for View. Need a way to find it. @BindingMethods({
        @BindingMethod(type  =  View.class,
                                      attribute  =  “android:onClick",
                                      method  =  “setOnClickListener"}) Look for setOnClickListener in View void  setOnClickListener(View.OnClickListener  l)
  237. Event Handlers 
 55 <Button  …
  android:onClick=“@{isAdmin  ?  handler.adminClick  :

     handler.userClick}”  />
 No “setOnClick” method for View. Need a way to find it. @BindingMethods({
        @BindingMethod(type  =  View.class,
                                      attribute  =  “android:onClick",
                                      method  =  “setOnClickListener"})   Look for setOnClickListener in View void  setOnClickListener(View.OnClickListener  l)   Look for single abstract method in OnClickListener void  onClick(View  v);
  238. Event Handlers 
 55

  239. Event Handlers 
 56

  240. Event Handlers 
 56 static  class  OnClickListenerImpl1  implements  OnClickListener  {


           public  Handler  mHandler;
        @Override
        public  void  onClick(android.view.View  arg0)  {
                mHandler.adminClick(arg0);
        }
 }
 static  class  OnClickListenerImpl2  implements  OnClickListener  {
        public  Handler  mHandler;
        @Override
        public  void  onClick(android.view.View  arg0)  {
                mHandler.userClick(arg0);
        }
 }
  241. Event Handlers 
 56

  242. Source: place source info here 57 Why Data Binding How

    Data Binding Works Data Binding Goodies Observability in Detail Performance RecyclerView / ListView and Data Binding Binding Adapters and Callbacks Best Practices 8 2 3 4 5 6 1 7
  243. Source: place source info here No Business Logic in Expressions

    58
  244. Source: place source info here No Business Logic in Expressions

    58 <ImageView android:click=“ "/> @{webservice.sendMoneyAsync}
  245. Source: place source info here No Business Logic in Expressions

    58 <ImageView android:click=“ "/>
  246. Source: place source info here No Business Logic in Expressions

    58 <ImageView android:click=“ "/> @{presenter.onSendClick}
  247. Source: place source info here Simple UI Logic is Welcome

    59 <ImageView android:src="@{user.age > 18 ? @drawable/adult : @drawable/kid}"
 />
  248. Source: place source info here <TextView
 android:text=‘@{user.age > 18 ?

    Keep your expressions simple 60 user.name.substring(0,1).toUpperCase() + "." + user.lastName : @string/redacted}’/>
  249. Source: place source info here <TextView
 android:text=‘@{user.age > 18 ?

    Keep your expressions simple 60 user.displayName : @string/redacted}’/>
  250. Source: place source info here <TextView
 android:text=‘@{user.age > 18 ?

    Keep your expressions simple 60 @Bindable
 public String getDisplayName() {
 return mName.substring(0, 1).toUpperCase() + "." + mLastName;
 } user.displayName : @string/redacted}’/>
  251. Source: place source info here <TextView
 android:text=‘@{user.age > 18 ?

    Keep your expressions simple 60 @Bindable
 public String getDisplayName() {
 return mName.substring(0, 1).toUpperCase() + "." + mLastName;
 } user.displayName : @string/redacted}’/> public void setLastName(String lastName) {
 …
 notifyPropertyChanged(BR.displayName);
 }
  252. Source: place source info here Consider using a ViewModel 61

    public class ProfileViewModel {
 
 }
  253. Source: place source info here Consider using a ViewModel 61

    public class ProfileViewModel {
 
 } public final ObservableInt friendCount; public final ObservableField<Date> subscriptionDate;
  254. Source: place source info here Consider using a ViewModel 62

    public class ProfileViewModel
 
 
 } extends BaseObservable {
  255. Source: place source info here Consider using a ViewModel 62

    public class ProfileViewModel
 
 
 private @Bindable String mDisplayName; } extends BaseObservable {
  256. Source: place source info here Consider using a ViewModel 62

    public class ProfileViewModel
 
 
 public void setUser(User user) { mDisplayName.set(user.getName() + " " + user.getLastName()); } private @Bindable String mDisplayName; } extends BaseObservable {
  257. Source: place source info here Consider using a ViewModel 62

    public class ProfileViewModel
 
 
 public void setUser(User user) { mDisplayName.set(user.getName() + " " + user.getLastName()); } private @Bindable String mDisplayName; notifyPropertyChange(BR.displayName); } extends BaseObservable {
  258. Source: place source info here Consider using a ViewModel 62

    public class ProfileViewModel
 
 
 public void setUser(User user) { mDisplayName.set(user.getName() + " " + user.getLastName()); } private @Bindable String mDisplayName; notifyPropertyChange(BR.displayName); } extends BaseObservable { public String getDisplayName(){…}
  259. Source: place source info here Consider using a ViewModel 62

    public class ProfileViewModel
 
 
 public void setUser(User user) { mDisplayName.set(user.getName() + " " + user.getLastName()); } private @Bindable String mDisplayName; notifyPropertyChange(BR.displayName); } implements Observable { public String getDisplayName(){…}
  260. Source: place source info here Consider using a ViewModel 62

    public class ProfileViewModel
 
 
 public void setUser(User user) { mDisplayName.set(user.getName() + " " + user.getLastName()); } private @Bindable String mDisplayName; notifyPropertyChange(BR.displayName); PropertyChangeRegistry mRegistry = new PropertyChangeRegistry(); } implements Observable { public String getDisplayName(){…}
  261. Source: place source info here Consider using a ViewModel 62

    public class ProfileViewModel
 
 
 public void setUser(User user) { mDisplayName.set(user.getName() + " " + user.getLastName()); } private @Bindable String mDisplayName; notifyPropertyChange(BR.displayName); PropertyChangeRegistry mRegistry = new PropertyChangeRegistry(); } implements Observable { mRegistry. public String getDisplayName(){…}
  262. Source: place source info here Consider using a ViewModel 62

    public class ProfileViewModel
 
 
 public void setUser(User user) { mDisplayName.set(user.getName() + " " + user.getLastName()); } private @Bindable String mDisplayName; notifyPropertyChange(BR.displayName); PropertyChangeRegistry mRegistry = new PropertyChangeRegistry(); } implements Observable { mRegistry. public String getDisplayName(){…}
  263. Source: place source info here Consider using a ViewModel 62

    public class ProfileViewModel
 
 
 public void setUser(User user) { mDisplayName.set(user.getName() + " " + user.getLastName()); } private @Bindable String mDisplayName; notifyPropertyChange(BR.displayName); PropertyChangeRegistry mRegistry = new PropertyChangeRegistry(); } implements Observable { public void addOnPropertyChangedCallback(OnPropertyChangedCallback cb) { mRegistry.add(cb); } public void removeOnPropertyChangedCallback(OnPropertyChangedCallback cb) { mRegistry.remove(cb); } mRegistry. public String getDisplayName(){…}
  264. Source: place source info here <TextView app:font="@{`Source-Sans-Pro-Regular.ttf`}"/> Take advantage of

    BindingAdapters 63
  265. Source: place source info here <TextView app:font="@{`Source-Sans-Pro-Regular.ttf`}"/> Take advantage of

    BindingAdapters 63 public class AppAdapters {
 @BindingAdapter({“font"})
 
 }
  266. Source: place source info here <TextView app:font="@{`Source-Sans-Pro-Regular.ttf`}"/> Take advantage of

    BindingAdapters 63 public class 
 } public static void setFont(TextView textView, String fontName){
 AssetManager assetManager = textView.getContext().getAssets();
 String path = "fonts/" + fontName;
 
 
 
 }
  267. Source: place source info here <TextView app:font="@{`Source-Sans-Pro-Regular.ttf`}"/> Take advantage of

    BindingAdapters 63 public class 
 } public static void AssetManager assetManager = textView.getContext().getAssets(); String path = 
 
 
 } Typeface.createFromAsset(assetManager, path); textView.setTypeface(typeface); Typeface typeface =
  268. Source: place source info here <TextView app:font="@{`Source-Sans-Pro-Regular.ttf`}"/> Take advantage of

    BindingAdapters 63 public class 
 } public static void AssetManager assetManager = textView.getContext().getAssets(); String path = 
 
 
 } Typeface.createFromAsset(assetManager, path); sCache.get(path); if (typeface == null) { typeface = sCache.put(path, typeface); } textView.setTypeface(typeface); Typeface typeface =
  269. Source: place source info here <TextView app:font="@{`Source-Sans-Pro-Regular.ttf`}"/> Take advantage of

    BindingAdapters 63 public class AppAdapters {
 @BindingAdapter({“font"})
 
 } public static void setFont(TextView textView, String fontName){
 AssetManager assetManager = textView.getContext().getAssets();
 String path = "fonts/" + fontName;
 
 
 
 } Typeface.createFromAsset(assetManager, path); sCache.get(path); if (typeface == null) { typeface = sCache.put(path, typeface); } textView.setTypeface(typeface); Typeface typeface =
  270. Source: place source info here 
 
 public defaultImage) {


    
 }
 } Use DataBindingComponent 64 static void setUrl(ImageView imageView, String url, Drawable public class ImageAdapter { @BindingAdapter(value={"photoUrl", "default"}, requireAll = false) Glide.with(imageView.getContext())
 .load(url).into(imageView)
 .onLoadStarted(defaultImage);
  271. Source: place source info here 
 
 public defaultImage) {


    
 }
 } Use DataBindingComponent 64 void setUrl(ImageView imageView, String url, Drawable public class ImageAdapter { @BindingAdapter(value={"photoUrl", "default"}, requireAll = false) Glide.with(imageView.getContext())
 .load(url).into(imageView)
 .onLoadStarted(defaultImage);
  272. public class AppComponent implements DataBindingComponent { } public ImageAdapter getImageAdapter()

    {
 return mImageAdapter;
 }
 Source: place source info here 
 
 public defaultImage) {
 
 }
 } Use DataBindingComponent 64 void setUrl(ImageView imageView, String url, Drawable public class ImageAdapter { @BindingAdapter(value={"photoUrl", "default"}, requireAll = false) Glide.with(imageView.getContext())
 .load(url).into(imageView)
 .onLoadStarted(defaultImage); ImageAdapter mImageAdapter = new ImageAdapter();
  273. public class AppComponent implements DataBindingComponent { } public ImageAdapter getImageAdapter()

    {
 return mImageAdapter;
 }
 Source: place source info here 
 
 public defaultImage) {
 
 }
 } Use DataBindingComponent 64 void setUrl(ImageView imageView, String url, Drawable public class MockImageAdapter extends ImageAdapter { @BindingAdapter(value={"photoUrl", "default"}, requireAll = false) Glide.with(imageView.getContext())
 .load(url).into(imageView)
 .onLoadStarted(defaultImage); ImageAdapter mImageAdapter = new ImageAdapter();
  274. public class AppComponent implements DataBindingComponent { } public ImageAdapter getImageAdapter()

    {
 return mImageAdapter;
 }
 Source: place source info here 
 
 public defaultImage) {
 
 }
 } Use DataBindingComponent 64 void setUrl(ImageView imageView, String url, Drawable public class MockImageAdapter extends ImageAdapter { @Override Glide.with(imageView.getContext())
 .load(url).into(imageView)
 .onLoadStarted(defaultImage); ImageAdapter mImageAdapter = new ImageAdapter();
  275. public class AppComponent implements DataBindingComponent { } public ImageAdapter getImageAdapter()

    {
 return mImageAdapter;
 }
 Source: place source info here 
 
 public defaultImage) {
 
 }
 } Use DataBindingComponent 64 void setUrl(ImageView imageView, String url, Drawable public class MockImageAdapter extends ImageAdapter { imageView.setImageDrawable(defaultImage); @Override ImageAdapter mImageAdapter = new ImageAdapter();
  276. public class TestComponent extends AppComponent { } public ImageAdapter getImageAdapter()

    {
 return mImageAdapter;
 }
 Source: place source info here 
 
 public defaultImage) {
 
 }
 } Use DataBindingComponent 64 void setUrl(ImageView imageView, String url, Drawable public class MockImageAdapter extends ImageAdapter { imageView.setImageDrawable(defaultImage); @Override ImageAdapter mImageAdapter = new ImageAdapter();
  277. public class TestComponent extends AppComponent { } public ImageAdapter getImageAdapter()

    {
 return mImageAdapter;
 }
 MockImageAdapter mMockImageAdapter = new MockImageAdapter(); Source: place source info here 
 
 public defaultImage) {
 
 }
 } Use DataBindingComponent 64 void setUrl(ImageView imageView, String url, Drawable public class MockImageAdapter extends ImageAdapter { imageView.setImageDrawable(defaultImage); @Override
  278. public class TestComponent extends AppComponent { } @Override public ImageAdapter

    getImageAdapter() { return mMockImageAdapter; } MockImageAdapter mMockImageAdapter = new MockImageAdapter(); Source: place source info here 
 
 public defaultImage) {
 
 }
 } Use DataBindingComponent 64 void setUrl(ImageView imageView, String url, Drawable public class MockImageAdapter extends ImageAdapter { imageView.setImageDrawable(defaultImage); @Override
  279. Source: place source info here DataBinding Dependency Injection 65 public

    class AppComponent implements DataBindingComponent { } public ImageAdapter getImageAdapter() {
 return mImageAdapter;
 }
 ImageAdapter mImageAdapter = new ImageAdapter();
  280. Source: place source info here DataBinding Dependency Injection 65 public

    class AppComponent implements DataBindingComponent { } public ImageAdapter getImageAdapter() {
 return mImageAdapter;
 }
 @Inject ImageAdapter mImageAdapter;
  281. Dagger 2 Example 
 66 @Component(modules  =  ProductionModule.class)
 public  interface

     ProductionComponent  extends  DataBindingComponent  {}   @Module
 public  class  ProductionModule  {
        @Provides
        TestableAdapter  provideTestableAdapter()  {
                return  new  ProductionAdapter();
        }
 }   DataBindingUtil.setDefaultComponent(          ProductionComponent.builder().build());
  282. Source: place source info here 67 Make better
 decisions by

    accessing unique customer, industry and performance insights Win moments
 that matter by engaging billions of people, in the right context, with personalized experiences they love What we do: Google makes the web work for you We help you: Go bigger,
 faster by tapping into technology that works together, across your business needs
  283. Source: place source info here Large placeholder 
 for segue

    here 68
  284. Source: place source info here “Lorem ipsum dolor sit amet,

    consectetuer adipiscing elit. Donec sollicitudin libero id elit. Sed euismod nonummy neque nam.” Name Title/company 69
  285. Source: place source info here Agenda slide 70 First item

    Second item Third item Fourth item Fifth item Sixth item Seventh item 1 2 3 4 5 6 7
  286. Source: place source info here Agenda slide 71 First item

    Second item Third item Fourth item Fifth item Sixth item Seventh item
  287. Source: place source info here One line title placeholder goes

    here
 • Bullets are set in 22 point Open Sans font – Second-line bullets are Open Sans 20pt • Third level bullets are Open Sans 18pt • See source placeholder below* (Open Sans 8pt) • Limit the number of bullets on a slide • Text highlights are blue color • Try not to go below the recommended font sizes 72
  288. Click to edit Master text styles Source: place source info

    here Title placeholder goes here • Bullets are set in 22 point Open Sans font – Second-line bullets are Open Sans 18pt • Third level bullets are Open Sans 16pt • See source placeholder below* (Open Sans 8pt) • Limit the number of bullets on a slide • Text highlights are blue color • Try not to go below the recommended font sizes 73
  289. Click to edit Master text styles Source: place source info

    here Two line title
 placeholder goes here
 • Bullets are set in 22 point Open Sans font – Second-line bullets are Open Sans 18pt • Third level bullets are Open Sans 16pt • See source placeholder below* (Open Sans 8pt) • Limit the number of bullets on a slide • Text highlights are blue color • Try not to go below the recommended font sizes 74
  290. • Click to edit Master text styles • Click to

    edit Master text styles Click to edit master text styles Click to edit master text styles Click to edit Master text styles Source: place source info here Title placeholder goes here 75
  291. Click to edit Master text styles Source: place source info

    here Title placeholder goes here • This is a sample of a bullet slide with a photo • If you have too many items to fit on one page remember that you can always use another slide • This works better than reducing the font size • Better yet, try to convey your message with images 76
  292. Click to edit Master text styles Source: place source info

    here • This is a sample of a bullet slide with a bar chart • If you have too many items to fit on one page remember that you can always use another slide • This works better than reducing the font size • Better yet, try to convey your message with image Title placeholder goes here 77 0 1 2 3 4 5 6 Sales Profit Growth Revenue Q1 Q2 Q3 Q4
  293. Source: place source info here 78

  294. Source: place source info here 79 Large text placeholder

  295. Source: place source info here 80

  296. Source: place source info here 81

  297. Source: place source info here 82

  298. Source: place source info here 83 • Bullet one here

    • Bullet two here • Bullet three here Place text here Place text here Place text here • Bullet one here • Bullet two here • Bullet three here • Bullet one here • Bullet two here • Bullet three here
  299. Source: place source info here Click to edit Master text

    styles Two line title placeholder goes here 84 Place text here Place text here Place text here • Bullet one here • Bullet two here • Bullet three here • Bullet one here • Bullet two here • Bullet three here • Bullet one here • Bullet two here • Bullet three here
  300. Source: place source info here Performance summary 85 State of

    the union Partnership update 1. Steady year in 2010 covario investment with google, lagging peers in growth $39m – 2010 covario investment with google (5.5% yoy growth) $27m – investment from top 2 clients (adobe, intel) $38m – 2010 covario investment in search and gdn text (98% of total) 4 – only 4 clients (intel, campmor, tek, solar) have invested in display in 2010 2. Limited presence in non-search opportunities. Ripe time to significantly advance leadership position 1. Certification! 2 people certified in 2010 2. Client business reviews with industry teams dec’10; jan, apr ‘11 3. Inflectionpoint feb’10, thinkagency march ‘10, agencycouncil dec’10 4. Inflectionpoint ‘11, sd strategy meetings, on-boarding new clients, @la, tv webinar
  301. Source: place source info here Column 1 Column 2 Column

    3 Column 4 Row 1 Placeholder Placeholder Placeholder Placeholder Row 2 Placeholder Placeholder Placeholder Placeholder Row 3 Placeholder Placeholder Highlight Placeholder Row 4 Placeholder Placeholder Placeholder Placeholder Row 5 Placeholder Placeholder Placeholder Placeholder Row 6 Placeholder Placeholder Placeholder Placeholder Row 7 Placeholder Placeholder Placeholder Placeholder 86
  302. Source: place source info here 0 8 17 25 33

    42 50 2005 2006 2007 2008 2009 2010 2011 87
  303. Source: place source info here 0 1 2 3 4

    5 6 Sales Profit Growth Revenue Q1 Q2 Q3 Q4 88
  304. Source: place source info here 0 8 17 25 33

    42 50 Q1 Q2 Q3 Q4 Series 1 Series 2 Series 3 Series 4 Series 5 89
  305. Source: place source info here 0 0.1 0 0.3 0.6

    Q1 Q2 Q3 Q1 Q5 90
  306. Source: place source info here Color palette 91 Gradient colors

    Flat colors Neutral colors Color picker R:213 G:15 B:37 R:51 G:105 B:232 R:0 G:153 B:37 R:238 G:178 B:17 R:51 G:51 B:54 R:95 G:97 B:101 R:158 G:160 B:164 R:219 G:219 B:221 R:213 G:15 B:37 R:51 G:105 B:232 R:0 G:153 B:37 R:238 G:178 B:17 R:180 G:0 B:0 R:12 G:83 B:198 R:0 G:130 B:15 R:245 G:153 B:0