Data Binding
2016-06-01 16:49
357 查看
第一步 配置
在build.gradle文件
第二步 编写Data Binding布局文件
<variable/> 用来声明变量,name变量名字,type类型包名+类名
使用:@{user.username},会调用user.getUsername方法或username()方法
第三步 Binding Data
Data Binding布局文件,会生成布局文件名对应的类,例如:main_activity.xml,生成MainActivityBinding类,如果<data/>没有子标签,不会生成
在onCreate方法中,不要调用setContentView,用下面代码替代
可以这样
如果布局文件,包括ListView,RecyclerView
Binding Events
和绑定数据差不多
特殊点击事件
Data Binding 布局详解
Imports:引入类,像Java一样引入类。
如果引入多个相同类名,可以使用alias指定别名
集合,后面User表示泛型
引入静态field或方法
Variables
有个默认的context变量,被binding表达式使用。root View的getContext()。如果声明了context变量,覆盖功能就不起作用。
自定义生成Binding Class名字
<dataclass="ContactItem"> </data>
<data class=".ContactItem"> </data>
<data class="com.demo.ContactItem"> </data>
Includes
指定命名空间 xmlns:bind="http://schemas.android.com/apk/res-auto" ,name.xml必须有个
不支持
Expression Language
有很多像Java expression
Mathematical
String concatenation
Logical
Binary
Unary
Shift
Comparison
Grouping
Literals - character, String, numeric,
Cast
Method calls
Field access
Array access
Ternary operator
没有的操作
Explicit generic invocation
Null Coalescing Operator (??)
空操作,左边表达式不空时,使用左边表达式值,否则使用右边表达式值
android:text="@{user.displayName
?? user.lastName}"
避免空指针错误
@{user.name} 如果user为空,那么user.name为null,基本类型是默认值
集合,array,list,map可以使用
字符串,可以使用单双引号交替,就像前端那种写法
Resources
后面firstName,lastName是参数,等于调用getResources.getString(R.string.nameFormat, firstName, lastName);
Data Objects
Data Binding 使用的POJO对象,POJO对象改变,不会通知UI更新的。Data Binding提供三种数据改变通知机制:
Observable
objects, observable
fields, and observable
collection
Observalbe Objects
Observable 接口有增加和移除listener方法,通过变换由开发者调用,可以继承它的子类BaseObservable.
在getter方法上添加@Bindable注解,该注解在编译时生成BR类,在module
package默认根包下
在setter通知数据变化notifyPropertyChanged(BR.firstName);
ObservableFields
还有
and
使用:
Observable Collections
把原来使用的集合类,换成下面这种
生成 Binding
创建
根据Id生成View对象
这机制比findViewById更快
变量
每个变量都提供访问方法
ViewStubs
viewStub介绍http://blog.csdn.net/hitlion2008/article/details/6737537/
当viewstub inflate布局时,binding需要为新的布局重新创建,ViewStubProxy监听
Advanced Binding
binding class需要动态生成,例如RecyclerView.Adapter,在Holder提供getBinding方法返回Binding对象
变量数据变化时,binding将会下一帧改变,如果需要立即执行,调用 executePendingBindings()方法
只要不是集合变量数据,可以后台线程进行修改数据值,不用担心同步问题。Data binding will localize each variable / field
Attribute Setters
对于一个属性,data binding尽量找setAttribute方法,命名空间不重要,主要是属性名字
例如:DrawerLayout 没有任何属性,但提供大量的setter方法,所有能这样使用。
<android.support.v4.widget.DrawerLayout app:scrimColor="@{@color/scrim}"
app:drawerListener="@{fragment.drawerListener}"/>
Renamed Setters
更改属性关联的setter方法,替换原来的setter方法,通过BindingMethods注解关联一个setter方法,
Custom Setters
有的属性需要自定义binding逻辑,例如:
接受多个参数
Binding adapter接受属性的old value
事件处理只有一个抽象方法的接口或抽象类
事件处理有多个抽象方法的接口或抽象类,例如View.OnAttachStateChangeListener
Converters
Object Conversions 对象转换
userMap返回的对象,会传进setText(CharSequence)方法当为参数
Custom Conversions
当@{}返回的类型和android属性需要类型不一样时,可以是Conversions进行转换
在binding activity添加下面代码
不允许混合类型
Android Studio Support for Data Binding
Syntax highlighting
Flagging of expression language syntax errors
XML code completion
References, including navigation (such as navigate
to a declaration) and quick documentation
参考资源
http://blog.csdn.net/johnny901114/article/details/50706329
https://www.aswifter.com/2015/07/09/android-data-binding-3/
http://www.jianshu.com/p/b1df61a4df77
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0603/2992.html
http://blog.csdn.net/jmq_0000/article/details/46658765
http://www.open-open.com/lib/view/open1433580995390.html
在build.gradle文件
android { .... dataBinding { enabled =true } }
第二步 编写Data Binding布局文件
<?xml version="1.0" encoding="utf-8"?> <layoutxmlns:android="http://schemas.android.com/apk/res/android"> <data> <variablename="user"type="com.example.User"/> </data> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> </LinearLayout> </layout>
<variable/> 用来声明变量,name变量名字,type类型包名+类名
使用:@{user.username},会调用user.getUsername方法或username()方法
<TextViewandroid:text="@{user.username}"
第三步 Binding Data
Data Binding布局文件,会生成布局文件名对应的类,例如:main_activity.xml,生成MainActivityBinding类,如果<data/>没有子标签,不会生成
在onCreate方法中,不要调用setContentView,用下面代码替代
MainActivityBinding binding =DataBindingUtil.setContentView(this, R.layout.main_activity); User user =newUser("Test","User"); binding.setUser(user);
可以这样
MainActivityBinding binding =MainActivityBinding.inflate(getLayoutInflater());
如果布局文件,包括ListView,RecyclerView
ListItemBinding binding =ListItemBinding.inflate(layoutInflater, viewGroup,false); //or ListItemBinding binding =DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup,false);
Binding Events
和绑定数据差不多
publicclass ButtonHandler{ publicvoid click(View view){...} }
<variablename="handler"type="com.example.Handler"/>
<Button android:onClick="@{handlers.click}"/>
特殊点击事件
Class | Listener Setter | Attribute |
---|---|---|
SearchView | setOnSearchClickListener(View.OnClickListener) | android:onSearchClick |
ZoomControls | setOnZoomInClickListener(View.OnClickListener) | android:onZoomIn |
ZoomControls | setOnZoomOutClickListener(View.OnClickListener) | android:onZoomOut |
Imports:引入类,像Java一样引入类。
<data> <importtype="android.view.View"/> </data>
<TextViewandroid:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>
如果引入多个相同类名,可以使用alias指定别名
<importtype="com.example.real.estate.View"alias="Vista"/>
集合,后面User表示泛型
<variablename="userList"type="List<User>"/>
引入静态field或方法
java.lang.*里的类自动引入
Variables
有个默认的context变量,被binding表达式使用。root View的getContext()。如果声明了context变量,覆盖功能就不起作用。
自定义生成Binding Class名字
<dataclass="ContactItem"> </data>
<data class=".ContactItem"> </data>
<data class="com.demo.ContactItem"> </data>
Includes
指定命名空间 xmlns:bind="http://schemas.android.com/apk/res-auto" ,name.xml必须有个
user
变量
<LinearLayout> <includelayout="@layout/name"bind:user="@{user}"/> </LinearLayout>
不支持
<merge> <includelayout="@layout/name" bind:user="@{user}"/> <includelayout="@layout/contact" bind:user="@{user}"/> </merge>
Expression Language
有很多像Java expression
Mathematical
+ - / * %
String concatenation
+
Logical
&& ||
Binary
& | ^
Unary
+ - ! ~
Shift
>> >>> <<
Comparison
== > < >= <=
instanceof
Grouping
()
Literals - character, String, numeric,
null
Cast
Method calls
Field access
Array access
[]
Ternary operator
?:
没有的操作
this
super
new
Explicit generic invocation
Null Coalescing Operator (??)
空操作,左边表达式不空时,使用左边表达式值,否则使用右边表达式值
android:text="@{user.displayName
?? user.lastName}"
避免空指针错误
@{user.name} 如果user为空,那么user.name为null,基本类型是默认值
集合,array,list,map可以使用
[]操作符访问
android:text="@{list[index]}" android:text="@{map[key]}"
字符串,可以使用单双引号交替,就像前端那种写法
android:text='@{map["firstName"]}'
Resources
android:text="@{@string/nameFormat(firstName, lastName)}"
后面firstName,lastName是参数,等于调用getResources.getString(R.string.nameFormat, firstName, lastName);
Type | Normal Reference | Expression Reference |
---|---|---|
String[] | @array | @stringArray |
int[] | @array | @intArray |
TypedArray | @array | @typedArray |
Animator | @animator | @animator |
StateListAnimator | @animator | @stateListAnimator |
color int | @color | @color |
ColorStateList | @color | @colorStateList |
Data Binding 使用的POJO对象,POJO对象改变,不会通知UI更新的。Data Binding提供三种数据改变通知机制:
Observable
objects, observable
fields, and observable
collection
Observalbe Objects
Observable 接口有增加和移除listener方法,通过变换由开发者调用,可以继承它的子类BaseObservable.
在getter方法上添加@Bindable注解,该注解在编译时生成BR类,在module
package默认根包下
在setter通知数据变化notifyPropertyChanged(BR.firstName);
ObservableFields
还有
ObservableBoolean,
ObservableByte,
ObservableChar,
ObservableShort,
ObservableInt,
ObservableLong,
ObservableFloat,
ObservableDouble,
and
ObservableParcelable
publicfinalObservableField<String> sex =newObservableField<>();
使用:
<TextView android:text="@{user.sex}"/>
user.sex.set("男"); int age = user.age.get();
Observable Collections
把原来使用的集合类,换成下面这种
ObservableArrayMap<String,Object> user =newObservableArrayMap<>();
ObservableArrayList<String> lists = new ObservableArrayList<>();
生成 Binding
创建
MyLayoutBinding binding =MyLayoutBinding.inflate(layoutInflater); MyLayoutBinding binding =MyLayoutBinding.inflate(layoutInflater, viewGroup,false);
MyLayoutBinding binding =MyLayoutBinding.bind(viewRoot);
ViewDataBinding binding =DataBindingUtil.inflate(LayoutInflater, layoutId, parent, attachToParent); ViewDataBinding binding =DataBindingUtil.bindTo(viewRoot, layoutId);
根据Id生成View对象
这机制比findViewById更快
<TextView android:id="@+id/username"/> <TextView android:id="@+id/userAge"/>
变量
每个变量都提供访问方法
ViewStubs
viewStub介绍http://blog.csdn.net/hitlion2008/article/details/6737537/
当viewstub inflate布局时,binding需要为新的布局重新创建,ViewStubProxy监听
ViewStub's
ViewStub.OnInflateListener并及时创建binding,ViewStubProxy允许开发者设置OnInflateListener
,并创建binding
Advanced Binding
binding class需要动态生成,例如RecyclerView.Adapter,在Holder提供getBinding方法返回Binding对象
publicvoid onBindViewHolder(BindingHolder holder,int position){ final T item = mItems.get(position); holder.getBinding().setVariable(BR.item, item); holder.getBinding().executePendingBindings(); }
变量数据变化时,binding将会下一帧改变,如果需要立即执行,调用 executePendingBindings()方法
只要不是集合变量数据,可以后台线程进行修改数据值,不用担心同步问题。Data binding will localize each variable / field
Attribute Setters
对于一个属性,data binding尽量找setAttribute方法,命名空间不重要,主要是属性名字
例如:DrawerLayout 没有任何属性,但提供大量的setter方法,所有能这样使用。
<android.support.v4.widget.DrawerLayout app:scrimColor="@{@color/scrim}"
app:drawerListener="@{fragment.drawerListener}"/>
Renamed Setters
更改属性关联的setter方法,替换原来的setter方法,通过BindingMethods注解关联一个setter方法,
@BindingMethods({ @BindingMethod(type ="android.widget.ImageView", attribute ="android:tint", method ="setImageTintList"), })
Custom Setters
有的属性需要自定义binding逻辑,例如:
android:paddingLeft没有对应的setter方法,只存在setPadding(left, top, right, bottom)
@BindingAdapter("android:paddingLeft") public static void setPaddingLeft(View view,int padding){ view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()); }
接受多个参数
@BindingAdapter({"bind:imageUrl","bind:error"}) public static void loadImage(ImageView view,String url,Drawable error){ Picasso.with(view.getContext()).load(url).error(error).into(view); }
<ImageViewapp:imageUrl=“@{venue.imageUrl}” app:error=“@{@drawable/venueError}”/>
Binding adapter接受属性的old value
@BindingAdapter("android:paddingLeft") publicstaticvoid setPaddingLeft(View view,int oldPadding,int newPadding){ if(oldPadding != newPadding){ view.setPadding(newPadding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()); } }
事件处理只有一个抽象方法的接口或抽象类
@BindingAdapter("android:onLayoutChange") publicstaticvoid 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); } } }
事件处理有多个抽象方法的接口或抽象类,例如View.OnAttachStateChangeListener
@BindingAdapter("android:onViewAttachedToWindow") public static void setListener(View view, OnViewAttachedToWindow attached) { setListener(view, null, attached); } @BindingAdapter("android:onViewDetachedFromWindow") public static void setListener(View view, OnViewDetachedFromWindow detached) { setListener(view, detached, null); }
@BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"}) public static void setListener(View view, final OnViewDetachedFromWindow detach, final OnViewAttachedToWindow attach) { if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) { final OnAttachStateChangeListener newListener; if (detach == null && attach == null) { newListener = null; } else { newListener = new OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { if (attach != null) { attach.onViewAttachedToWindow(v); } } @Override public void onViewDetachedFromWindow(View v) { if (detach != null) { detach.onViewDetachedFromWindow(v); } } }; } final OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view, newListener, R.id.onAttachStateChangeListener); if (oldListener != null) { view.removeOnAttachStateChangeListener(oldListener); } if (newListener != null) { view.addOnAttachStateChangeListener(newListener); } } }
Converters
Object Conversions 对象转换
<TextView android:text='@{userMap["lastName"]}'/>
userMap返回的对象,会传进setText(CharSequence)方法当为参数
Custom Conversions
当@{}返回的类型和android属性需要类型不一样时,可以是Conversions进行转换
<Viewandroid:background="@{isError ? @color/red : @color/white}"/>
在binding activity添加下面代码
@BindingConversion
publicstaticColorDrawable convertColorToDrawable(int color){ returnnewColorDrawable(color); }
不允许混合类型
<Viewandroid:background="@{isError ? @drawable/error : @color/white}"/>
Android Studio Support for Data Binding
Syntax highlighting
Flagging of expression language syntax errors
XML code completion
References, including navigation (such as navigate
to a declaration) and quick documentation
<TextViewandroid:text="@{user.username, default=测试}"/> 提供默认值
参考资源
http://blog.csdn.net/johnny901114/article/details/50706329
https://www.aswifter.com/2015/07/09/android-data-binding-3/
http://www.jianshu.com/p/b1df61a4df77
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0603/2992.html
http://blog.csdn.net/jmq_0000/article/details/46658765
http://www.open-open.com/lib/view/open1433580995390.html
相关文章推荐
- WPF中数据绑定
- 如何使用Visual Studio 2010在数据库中生成随机测试数据
- win2008 R2服务器下修改MySQL 5.5数据库data目录的方法
- Windows Server 2003下修改MySQL 5.5数据库data目录
- 对 jQuery 中 data 方法的误解分析
- jquery load事件(callback/data)使用方法及注意事项
- jQuery中使用data()方法读取HTML5自定义属性data-*实例
- JQuery中attr属性和jQuery.data()学习笔记【必看】
- Javascript实现关联数据(Linked Data)查询及注意细节
- JQuery.Ajax()的data参数类型实例详解
- Select data from an Excel sheet in MSSQL
- js表数据排序 sort table data
- Mysql Data目录和 Binlog 目录 搬迁的方法
- mysql 卡死 大部分线程长时间处于sending data的状态
- ERROR 1406 : Data too long for column 解决办法
- mysql 的load data infile
- java复制文件和java移动文件的示例分享
- mysql Load Data InFile 的用法
- string中c_str(),data(),copy(p,n)函数的用法总结
- 解决MySQL Sending data导致查询很慢问题的方法与思路