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

Realm
September 23, 2015
88k

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

Realm

September 23, 2015
Tweet

Transcript

  1. 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
  2. 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());
  3. private protected void setContentView(R.layout. mName 
 
 4 ,mLastName mLastName

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

    = (TextView) findViewById(R.id.lastName); mLastName.setText(null); ; public void }
 } } else {
 }
  5. 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 {
 }
  6. 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());
  7. 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( );
  8. 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( );
  9. 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( );
  10. 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);
  11. 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);
  12. 
 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());
  13. 
 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());
  14. 
 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());
  15. 
 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());
  16. 
 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.
  17. 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
  18. 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
  19. 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());
 } }
  20. 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());
 } }
  21. 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; }
  22. 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; }
  23. Source: place source info here 
 protected void }
 public

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

    void 
 8 mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); private ActivityMainBinding mBinding; mBinding.setUser(user); }
  25. 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); }
  26. Source: place source info here 9 <TextView android: /> <TextView

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

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

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

    android: /> <LinearLayout …> </LinearLayout> text="@{user.name}" text="@{user.lastName}" ?
  30. 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>
  31. 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}"
  32. 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}’/>
  33. 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}’/>
  34. 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
  35. Source: place source info here What is happening ? 12

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

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

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

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

    What is happening ? 12 Process Layout Files Parse Expressions ID ID ID
  40. 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
  41. 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
  42. Source: place source info here What is happening ? 12

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

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

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

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

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

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

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

    Process Layout Files Parse Expressions Resolve Dependencies Write Data Binders
  50. <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}"
  51. Source: place source info here 14 <TextView android:text=“@{ }"/> user

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

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

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

    . age < 18 ? @string/redacted user . name : User getAge() int int boolean User getName() String
  55. 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
  56. 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
  57. 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
  58. 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)
  59. Source: place source info here Resolving Setters 15 <TextView textView.setText(myVariable);

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

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

    textView.setText(myVariable); <ImageView android:src="@{user.image}"/>
  62. 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")
  63. 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
  64. obj. Expression language is mostly Java 18 obj. obj. View.VISIBLE

    obj. obj. obj. obj.admin  ?  View.VISIBLE  :  View.GONE  
  65. Short and readable 19 Fields access shortcut contact.name   public

     String  name;   public  String  getName()  {…}   public  boolean  isName()  {…}   public  String  name()  {…}
  66. 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()  {…}
  67. 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()  {…}
  68. 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()  {…}
  69. 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
  70. 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
  71. Event Handlers 
 22 <Button  android:onClick="clicked"  …/>
 
 <Button  android:onClick="@{handlers.clicked}"

     …/> 
 
 <Button  android:onClick="@{isAdult  ?  handlers.adultClick  :   handlers.childClick}"  …/>
  72. 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}"  …/>
  73. 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
  74. 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);
        }
 }
  75. 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);
        }
 }
  76. 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);
        }
 }
  77. 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);
        }
 }
  78. 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);
        }
 }
  79. 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");
  80. 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");
  81. 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"]}'/>

  82. 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"]}'/>

  83. 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
  84. 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
  85. 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
  86. 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();
  87. Source: place source info here One Pass View Collection 36

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

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

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

    findAllViews(root, View[]) findAllViews(child[0], View[]) findAllViews(child[0], View[]) NO SECOND PASS
  91. 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
  92. 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
  93. 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; }
  94. 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(); }
  95. 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(); }
  96. 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));
 }
  97. Source: place source info here What happens when user is

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

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

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

    updated? 40 user.notifyPropertyChanged(BR.name); binding.requestRebind(); textView.setText(user.name); textView.requestLayout();
  101. 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(…);
  102. 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!
  103. Source: place source info here What we want it to

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

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

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

    happen? 41 user.notifyPropertyChanged(BR.name); adapter.notifyItemChanged(…); adapter.onBind(…); recyclerView.onLayout(…);
  107. 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(…);
  108. 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!
  109. Source: place source info here 42 public UserViewHolder onCreateViewHolder(ViewGroup viewGroup,

    int i) {
 final UserViewHolder holder = UserViewHolder.create(mLayoutInflater, viewGroup);
 
 
 
 return holder;
 }
  110. 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;
 }
  111. 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) { }
  112. 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) { }
  113. 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();
  114. 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); }
  115. 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); }
  116. 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
  117. Source: place source info here 43 public void onBindViewHolder(UserViewHolder userViewHolder,

    int position) {
 userViewHolder.bindTo(mUserList.get(position));
 }
  118. 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) { }
  119. 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);
  120. 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) { }
  121. 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); }
  122. 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;
  123. 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;
  124. <layout>
 <data>
 <variable name="data" type=“com.example. "/>
 </data>
 
 Multiple View

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

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

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

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

    Place <TextView android:text=“@{data.name}" …/> <ImageView android:src="@{data.isFav ? @drawable/active : @drawable/passive}”
  129. <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}”
  130. Source: place source info here public class 
 
 }

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

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

    46 private public } public ViewDataBinding getBinding() { return mBinding; }
  133. 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
  134. 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
  135. Source: place source info here public class 
 
 }

    46 private public } public ViewDataBinding getBinding() { return mBinding; } public void bindTo( ) { mBinding mBinding.executePendingBindings(); }
  136. .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(); }
  137. .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; }
  138. 47 DataBoundViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
 return DataBoundViewHolder.create(mLayoutInflater, viewGroup,

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

    public int getItemViewType(int position) { Object item = mItems.get(position);
 
 }
  140. 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");
  141. 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");
  142. 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
  143. Something a bit more complex than setText
 50 <ImageView  …


           android:src="@{contact.largeImageUrl}"  />
  144. 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);
 }
  145. 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);
 }
  146. 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);
                }
        }
 }
  147. Dependency Injection
 53 public  interface  TestableAdapter  {
      

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

  148. Dependency Injection
 53 public  interface  TestableAdapter  {
      

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

  149. Dependency Injection
 53 public  interface  TestableAdapter  {
      

     @BindingAdapter("android:src")
        void  setImageUrl(ImageView  imageView,  String  url);
 }
 public  interface  DataBindingComponent  {
        TestableAdapter  getTestableAdapter();
 }
 DataBindingUtil.setDefaultComponent(myComponent);
  150. 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);
  151. Component For Context 
 54 @BindingAdapter("android:src")
 public  static  void  setImageUrl(MyAppComponent

     component,                                                                ImageView  view,                                                                String  imageUrl)  {
        component.getImageCache().loadInto(view,  imageUrl);
 }
  152. 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"})
  153. 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)
  154. 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);
  155. 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);
        }
 }
  156. 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
  157. Source: place source info here No Business Logic in Expressions

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

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

    59 <ImageView android:src="@{user.age > 18 ? @drawable/adult : @drawable/kid}"
 />
  160. 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}’/>
  161. Source: place source info here <TextView
 android:text=‘@{user.age > 18 ?

    Keep your expressions simple 60 user.displayName : @string/redacted}’/>
  162. 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}’/>
  163. 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);
 }
  164. Source: place source info here Consider using a ViewModel 61

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

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

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

    public class ProfileViewModel
 
 
 private @Bindable String mDisplayName; } extends BaseObservable {
  168. 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 {
  169. 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 {
  170. 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(){…}
  171. 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(){…}
  172. 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(){…}
  173. 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(){…}
  174. 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(){…}
  175. 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(){…}
  176. Source: place source info here <TextView app:font="@{`Source-Sans-Pro-Regular.ttf`}"/> Take advantage of

    BindingAdapters 63 public class AppAdapters {
 @BindingAdapter({“font"})
 
 }
  177. 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;
 
 
 
 }
  178. 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 =
  179. 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 =
  180. 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 =
  181. 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);
  182. 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);
  183. 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();
  184. 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();
  185. 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();
  186. 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();
  187. 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();
  188. 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
  189. 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
  190. Source: place source info here DataBinding Dependency Injection 65 public

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

    class AppComponent implements DataBindingComponent { } public ImageAdapter getImageAdapter() {
 return mImageAdapter;
 }
 @Inject ImageAdapter mImageAdapter;
  192. 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());
  193. 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
  194. 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
  195. 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
  196. Source: place source info here Agenda slide 71 First item

    Second item Third item Fourth item Fifth item Sixth item Seventh item
  197. 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
  198. 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
  199. 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
  200. • 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
  201. 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
  202. 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
  203. 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
  204. 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
  205. 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
  206. 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
  207. Source: place source info here 0 8 17 25 33

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

    5 6 Sales Profit Growth Revenue Q1 Q2 Q3 Q4 88
  209. 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
  210. 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