Slide 1

Slide 1 text

Android Data Binding Building Apps Faster George Mount Yigit Boyar

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

3 


Slide 4

Slide 4 text

3 


Slide 5

Slide 5 text

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());

Slide 6

Slide 6 text

private protected void setContentView(R.layout. mName 
 
 4 ; public void }
 } } else {
 }

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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 {
 }

Slide 11

Slide 11 text

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());

Slide 12

Slide 12 text

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( );

Slide 13

Slide 13 text

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( );

Slide 14

Slide 14 text

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( );

Slide 15

Slide 15 text

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);

Slide 16

Slide 16 text

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);

Slide 17

Slide 17 text


 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());

Slide 18

Slide 18 text


 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());

Slide 19

Slide 19 text


 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());

Slide 20

Slide 20 text


 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());

Slide 21

Slide 21 text


 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.

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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());
 } }

Slide 25

Slide 25 text

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());
 } }

Slide 26

Slide 26 text

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; }

Slide 27

Slide 27 text

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; }

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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); }

Slide 31

Slide 31 text

Source: place source info here 9 id="@+id/name" id="@+id/lastName"

Slide 32

Slide 32 text

Source: place source info here 9

Slide 33

Slide 33 text

Source: place source info here 9 text="@{user.name}" text="@{user.lastName}"

Slide 34

Slide 34 text

Source: place source info here 9 text="@{user.name}" text="@{user.lastName}" ?

Slide 35

Slide 35 text

Source: place source info here 9 text="@{user.name}" text="@{user.lastName}" 
 
 


Slide 36

Slide 36 text

Source: place source info here 10 text="@{user.lastName}" 
 
 
 text="@{user.name}"

Slide 37

Slide 37 text

Source: place source info here 10 text="@{user.lastName}" 
 
 
 text="@{user.name}"

Slide 38

Slide 38 text

Source: place source info here 10 text="@{user.lastName}" 
 
 
 text="@{user.name}"

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

Source: place source info here What is happening ? 12

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text


 
 
 
 Source: place source info here 13 
 
 
 
 
 xmlns:android="http://schemas.android.com/apk/res/android" android:text="@{user.name}" android:text="@{user.lastname}"

Slide 58

Slide 58 text


 
 
 
 Source: place source info here 13 xmlns:android="http://schemas.android.com/apk/res/ android:text="@{user.name}" android:text="@{user.lastname}"

Slide 59

Slide 59 text


 
 
 
 Source: place source info here 13 xmlns:android="http://schemas.android.com/apk/res/

Slide 60

Slide 60 text


 
 
 
 Source: place source info here 13 xmlns:android="http://schemas.android.com/apk/res/ android:tag="binding_1" android:tag="binding_2"

Slide 61

Slide 61 text

Source: place source info here 14 user.age < 18 ? @string/redacted user.name :

Slide 62

Slide 62 text

Source: place source info here 14 user.age < 18 ? @string/redacted user.name :

Slide 63

Slide 63 text

Source: place source info here 14 user . age < 18 ? @string/redacted user . name :

Slide 64

Slide 64 text

Source: place source info here 14 user . age < 18 ? @string/redacted user . name : User int User String

Slide 65

Slide 65 text

Source: place source info here 14 user . age < 18 ? @string/redacted user . name : User getAge() int User String

Slide 66

Slide 66 text

Source: place source info here 14 user . age < 18 ? @string/redacted user . name : User getAge() int int boolean User String

Slide 67

Slide 67 text

Source: place source info here 14 user . age < 18 ? @string/redacted user . name : User getAge() int int boolean User getName() String

Slide 68

Slide 68 text

Source: place source info here 14 user . age < 18 ? @string/redacted user . name : User getAge() int int boolean User getName() String String

Slide 69

Slide 69 text

Source: place source info here 14 user . age < 18 ? @string/redacted user . name : User getAge() int int boolean User getName() String String String

Slide 70

Slide 70 text

Source: place source info here 14 user . age < 18 ? @string/redacted user . name : User getAge() int int boolean User getName() String String String

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

Source: place source info here Resolving Setters 15

Slide 73

Slide 73 text

Source: place source info here Resolving Setters 15

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

Source: place source info here Resolving Setters 15

Slide 76

Slide 76 text

Source: place source info here Resolving Setters 15 imageView.setSrc(user.image);

Slide 77

Slide 77 text

Source: place source info here Resolving Setters 15 imageView.setSrc(user.image);

Slide 78

Slide 78 text

imageView.setImageResource(user.image); Source: place source info here Resolving Setters 15

Slide 79

Slide 79 text

imageView.setImageResource(user.image); Source: place source info here Resolving Setters 15 @BindingMethod(
 type = android.widget.ImageView.class,
 attribute = "android:src",
 method = "setImageResource")

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

17 Goodies

Slide 82

Slide 82 text

Expression language is mostly Java 18

Slide 83

Slide 83 text

obj.name Expression language is mostly Java 18

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

obj. Expression language is mostly Java 18 obj. obj. View.VISIBLE obj. obj. obj. obj.admin  ?  View.VISIBLE  :  View.GONE  

Slide 91

Slide 91 text

Short and readable 19

Slide 92

Slide 92 text

Short and readable 19 Fields access shortcut contact.name   public  String  name;   public  String  getName()  {…}   public  boolean  isName()  {…}   public  String  name()  {…}

Slide 93

Slide 93 text

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()  {…}

Slide 94

Slide 94 text

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()  {…}

Slide 95

Slide 95 text

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()  {…}

Slide 96

Slide 96 text

Resources 20

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

Resources 20

Slide 101

Slide 101 text

Automagic Attributes 21

Slide 102

Slide 102 text

Automagic Attributes 
 
 drawerLayout.setScrimColor(
      resources.getColor(R.color.scrim)) 21

Slide 103

Slide 103 text

Automagic Attributes 21

Slide 104

Slide 104 text

Event Handlers 
 22

Slide 105

Slide 105 text

Event Handlers 
 22 


Slide 106

Slide 106 text

Event Handlers 
 22 
 


Slide 107

Slide 107 text

Event Handlers 
 22 
 
 
 


Slide 108

Slide 108 text

Event Handlers 
 22 
 
   
 
   
 


Slide 109

Slide 109 text

Event Handlers 
 22

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

24 Change

Slide 112

Slide 112 text

25 Image: pink_droid Price: $20.06

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

25 Image: pink_droid Price: $20.06

Slide 116

Slide 116 text

26 Image: pink_droid Price: $20.06

Slide 117

Slide 117 text

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);
        }
 }

Slide 118

Slide 118 text

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);
        }
 }

Slide 119

Slide 119 text

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);
        }
 }

Slide 120

Slide 120 text

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);
        }
 }

Slide 121

Slide 121 text

26 Image: pink_droid Price: $20.06

Slide 122

Slide 122 text

27 Image: pink_droid Price: $20.06

Slide 123

Slide 123 text

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);
        }
 }

Slide 124

Slide 124 text

27 Image: pink_droid Price: $20.06

Slide 125

Slide 125 text

28 Image: pink_droid Price: $20.06

Slide 126

Slide 126 text

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

Slide 127

Slide 127 text

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

Slide 128

Slide 128 text

28 Image: pink_droid Price: $20.06

Slide 129

Slide 129 text

29 Image: pink_droid Price: $20.06

Slide 130

Slide 130 text

29 Image: pink_droid Price: $20.06 ObservableMap  item  =
                new  ObservableArrayMap<>();
 item.put("price",  "$33.41");   


Slide 131

Slide 131 text

29 Image: pink_droid Price: $20.06 ObservableMap  item  =
                new  ObservableArrayMap<>();
 item.put("price",  "$33.41");   


Slide 132

Slide 132 text

29 Image: pink_droid Price: $20.06

Slide 133

Slide 133 text

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

Slide 134

Slide 134 text

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

Slide 135

Slide 135 text

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

Slide 136

Slide 136 text

Source: place source info here 32 No reflection

Slide 137

Slide 137 text

Source: place source info here 33

Slide 138

Slide 138 text

Source: place source info here 33

Slide 139

Slide 139 text

Source: place source info here 33

Slide 140

Slide 140 text

Source: place source info here 34 


Slide 141

Slide 141 text

Source: place source info here 34 


Slide 142

Slide 142 text

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

Slide 143

Slide 143 text

Source: place source info here findViewById Traversal 35

Slide 144

Slide 144 text

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

Slide 145

Slide 145 text

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

Slide 146

Slide 146 text

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

Slide 147

Slide 147 text

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

Slide 148

Slide 148 text

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

Slide 149

Slide 149 text

Source: place source info here One Pass View Collection 36

Slide 150

Slide 150 text

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

Slide 151

Slide 151 text

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

Slide 152

Slide 152 text

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

Slide 153

Slide 153 text

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

Slide 154

Slide 154 text

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

Slide 155

Slide 155 text

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

Slide 156

Slide 156 text

public class UserViewHolder extends RecyclerView.ViewHolder {
 
 
 } Source: place source info here 38

Slide 157

Slide 157 text

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

Slide 158

Slide 158 text

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; }

Slide 159

Slide 159 text

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(); }

Slide 160

Slide 160 text

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(); }

Slide 161

Slide 161 text

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));
 }

Slide 162

Slide 162 text

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

Slide 163

Slide 163 text

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

Slide 164

Slide 164 text

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

Slide 165

Slide 165 text

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

Slide 166

Slide 166 text

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(…);

Slide 167

Slide 167 text

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!

Slide 168

Slide 168 text

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

Slide 169

Slide 169 text

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

Slide 170

Slide 170 text

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

Slide 171

Slide 171 text

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

Slide 172

Slide 172 text

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(…);

Slide 173

Slide 173 text

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!

Slide 174

Slide 174 text

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

Slide 175

Slide 175 text

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;
 }

Slide 176

Slide 176 text

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) { }

Slide 177

Slide 177 text

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) { }

Slide 178

Slide 178 text

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();

Slide 179

Slide 179 text

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); }

Slide 180

Slide 180 text

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); }

Slide 181

Slide 181 text

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

Slide 182

Slide 182 text

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

Slide 183

Slide 183 text

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 payloads) { }

Slide 184

Slide 184 text

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 payloads) { } notifyItemChanged(position, DATA_INVALIDATION);

Slide 185

Slide 185 text

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 payloads) { }

Slide 186

Slide 186 text

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 payloads) { } if (isForDataBinding(payloads)) { holder.getBinding().executePendingBindings(); } else { onBindViewHolder(holder, position); }

Slide 187

Slide 187 text

Source: place source info here 44 private boolean isForDataBinding(List payloads) {
 
 }

Slide 188

Slide 188 text

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

Slide 189

Slide 189 text

Source: place source info here 44 private boolean isForDataBinding(List 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;

Slide 190

Slide 190 text


 
 
 
 
 Multiple View Types 45 Photo

Slide 191

Slide 191 text

Slide 192

Slide 192 text

Slide 193

Slide 193 text

Slide 194

Slide 194 text

Slide 195

Slide 195 text


 
 
 
 
 Multiple View Types 45 Place

Slide 196

Slide 196 text

Source: place source info here 46

Slide 197

Slide 197 text

Source: place source info here public class DataBoundViewHolder extends RecyclerView.ViewHolder {
 
 
 } 46

Slide 198

Slide 198 text

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

Slide 199

Slide 199 text

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

Slide 200

Slide 200 text

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

Slide 201

Slide 201 text

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

Slide 202

Slide 202 text

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

Slide 203

Slide 203 text

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

Slide 204

Slide 204 text

.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(); }

Slide 205

Slide 205 text

.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; }

Slide 206

Slide 206 text

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

Slide 207

Slide 207 text

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

Slide 208

Slide 208 text

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

Slide 209

Slide 209 text

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");

Slide 210

Slide 210 text

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");

Slide 211

Slide 211 text

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

Slide 212

Slide 212 text

49 Binding Adapters

Slide 213

Slide 213 text

Something a bit more complex than setText
 50

Slide 214

Slide 214 text

Something a bit more complex than setText
 50

Slide 215

Slide 215 text

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

Slide 216

Slide 216 text

Something a bit more complex than setText
 50

Slide 217

Slide 217 text

Attributes working together
 51

Slide 218

Slide 218 text

Attributes working together
 51

Slide 219

Slide 219 text

Attributes working together
 51   
 @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);
 }

Slide 220

Slide 220 text

Attributes working together
 51

Slide 221

Slide 221 text

Using Previous Values
 52

Slide 222

Slide 222 text

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);
                }
        }
 }

Slide 223

Slide 223 text

Using Previous Values
 52

Slide 224

Slide 224 text

Dependency Injection
 53

Slide 225

Slide 225 text

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


Slide 226

Slide 226 text

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


Slide 227

Slide 227 text

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

Slide 228

Slide 228 text

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);

Slide 229

Slide 229 text

Dependency Injection
 53

Slide 230

Slide 230 text

Component For Context 
 54

Slide 231

Slide 231 text

Component For Context 
 54 @BindingAdapter("android:src")
 public  static  void  setImageUrl(MyAppComponent  component,                                                                ImageView  view,                                                                String  imageUrl)  {
        component.getImageCache().loadInto(view,  imageUrl);
 }

Slide 232

Slide 232 text

Component For Context 
 54

Slide 233

Slide 233 text

Event Handlers 
 55

Slide 234

Slide 234 text

Event Handlers 
 55 


Slide 235

Slide 235 text

Event Handlers 
 55 
 No “setOnClick” method for View. Need a way to find it. @BindingMethods({
        @BindingMethod(type  =  View.class,
                                      attribute  =  “android:onClick",
                                      method  =  “setOnClickListener"})

Slide 236

Slide 236 text

Event Handlers 
 55 
 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)

Slide 237

Slide 237 text

Event Handlers 
 55 
 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);

Slide 238

Slide 238 text

Event Handlers 
 55

Slide 239

Slide 239 text

Event Handlers 
 56

Slide 240

Slide 240 text

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);
        }
 }

Slide 241

Slide 241 text

Event Handlers 
 56

Slide 242

Slide 242 text

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

Slide 243

Slide 243 text

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

Slide 244

Slide 244 text

Source: place source info here No Business Logic in Expressions 58 @{webservice.sendMoneyAsync}

Slide 245

Slide 245 text

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

Slide 246

Slide 246 text

Source: place source info here No Business Logic in Expressions 58 @{presenter.onSendClick}

Slide 247

Slide 247 text

Source: place source info here Simple UI Logic is Welcome 59

Slide 248

Slide 248 text

Source: place source info here 18 ? Keep your expressions simple 60 user.name.substring(0,1).toUpperCase() + "." + user.lastName : @string/redacted}’/>

Slide 249

Slide 249 text

Source: place source info here 18 ? Keep your expressions simple 60 user.displayName : @string/redacted}’/>

Slide 250

Slide 250 text

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

Slide 251

Slide 251 text

Source: place source info here 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);
 }

Slide 252

Slide 252 text

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

Slide 253

Slide 253 text

Source: place source info here Consider using a ViewModel 61 public class ProfileViewModel {
 
 } public final ObservableInt friendCount; public final ObservableField subscriptionDate;

Slide 254

Slide 254 text

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

Slide 255

Slide 255 text

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

Slide 256

Slide 256 text

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 {

Slide 257

Slide 257 text

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 {

Slide 258

Slide 258 text

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(){…}

Slide 259

Slide 259 text

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(){…}

Slide 260

Slide 260 text

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(){…}

Slide 261

Slide 261 text

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(){…}

Slide 262

Slide 262 text

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(){…}

Slide 263

Slide 263 text

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(){…}

Slide 264

Slide 264 text

Source: place source info here Take advantage of BindingAdapters 63

Slide 265

Slide 265 text

Source: place source info here Take advantage of BindingAdapters 63 public class AppAdapters {
 @BindingAdapter({“font"})
 
 }

Slide 266

Slide 266 text

Source: place source info here Take advantage of BindingAdapters 63 public class 
 } public static void setFont(TextView textView, String fontName){
 AssetManager assetManager = textView.getContext().getAssets();
 String path = "fonts/" + fontName;
 
 
 
 }

Slide 267

Slide 267 text

Source: place source info here 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 =

Slide 268

Slide 268 text

Source: place source info here 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 =

Slide 269

Slide 269 text

Source: place source info here 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 =

Slide 270

Slide 270 text

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);

Slide 271

Slide 271 text

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);

Slide 272

Slide 272 text

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();

Slide 273

Slide 273 text

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();

Slide 274

Slide 274 text

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();

Slide 275

Slide 275 text

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();

Slide 276

Slide 276 text

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();

Slide 277

Slide 277 text

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

Slide 278

Slide 278 text

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

Slide 279

Slide 279 text

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

Slide 280

Slide 280 text

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

Slide 281

Slide 281 text

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());

Slide 282

Slide 282 text

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

Slide 283

Slide 283 text

Source: place source info here Large placeholder 
 for segue here 68

Slide 284

Slide 284 text

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

Slide 285

Slide 285 text

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

Slide 286

Slide 286 text

Source: place source info here Agenda slide 71 First item Second item Third item Fourth item Fifth item Sixth item Seventh item

Slide 287

Slide 287 text

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

Slide 288

Slide 288 text

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

Slide 289

Slide 289 text

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

Slide 290

Slide 290 text

• 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

Slide 291

Slide 291 text

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

Slide 292

Slide 292 text

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

Slide 293

Slide 293 text

Source: place source info here 78

Slide 294

Slide 294 text

Source: place source info here 79 Large text placeholder

Slide 295

Slide 295 text

Source: place source info here 80

Slide 296

Slide 296 text

Source: place source info here 81

Slide 297

Slide 297 text

Source: place source info here 82

Slide 298

Slide 298 text

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

Slide 299

Slide 299 text

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

Slide 300

Slide 300 text

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

Slide 301

Slide 301 text

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

Slide 302

Slide 302 text

Source: place source info here 0 8 17 25 33 42 50 2005 2006 2007 2008 2009 2010 2011 87

Slide 303

Slide 303 text

Source: place source info here 0 1 2 3 4 5 6 Sales Profit Growth Revenue Q1 Q2 Q3 Q4 88

Slide 304

Slide 304 text

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

Slide 305

Slide 305 text

Source: place source info here 0 0.1 0 0.3 0.6 Q1 Q2 Q3 Q1 Q5 90

Slide 306

Slide 306 text

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