参考自
Android官方数据绑定框架DataBinding(一)
Android官方数据绑定框架DataBinding(二)
- 环境配置
app模块的bulid.gradle下
dataBinding{
enabled=true;
}
布局文件
- 以layout为根布局,并添加
<data>
节点,这样layout里面就分为2部分,一部分就是data 一部分就是我们的布局。 - 在data里面绑定数据
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.example.gzp.mvvmtest.Student"/>
<variable
name="stu"
type="student"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{stu.name}"/>
</LinearLayout>
</layout>
导入了一个student类 里面有name,add 属性 和相应的get,set方法。
或者type="com.example.gzp.mvvmtest.Student"
不用import。
type 支持基本数据类型和集合(list,map等)类型,类
<variable
name="num"
type="int" />
<variable
name="list"
type="ArrayList<String>"/>
< 符号需要转义
<
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{map[`name`]}"/>
集合变量名[key]的形式使用,如果你的key是一个字面字符串可以使用反引号,也可以使用转义后的双引号。
android:text='@{map["name"]}'
android:text="@{map["name"]}"
- 取别名
如果import了两个相同名称的类
<import type="com.example.gzp.mvvmtest.Student" alisa="mystu"/>
<import type="com.example.Student"/>
- xml里还可以调用函数
android:text="@{String.valueof(num)}"
还可以调用表达式
- 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
??表达式
android:text='@{str ?? "null"}'
等价于
android:text='@{str!=null ? str:"null"}'
java
ActivityMainBinding binding=
DataBindingUtil.setContentView(this,R.layout.activity_main);
ActivityMainBinding 自动生成的类,命名方法:
将我们布局文件的首字母大写,并且去掉下划线,将下划线后面的字母大写,加上Binding组成。
- 自定义类
在xml文件中
<data class=".Custom">
…..
</data>
包名.Custom binding=DataBindingUtil.XXXXXX();
给对应的变量赋值
binding=setXXXX;
XXX为我们在布局文件定义的变量首字母大写
binding.setStr("string");
binding.setList(arrayList);
- 获取实例
当我们需要某个view的实例时,我们只要给该view一个id,然后Data Binding框架就会给我们自动生成该view的实例
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{stu.name}"/>
mBinding.textView.setTextColor(Color.GREEN);
* 事件的绑定
……
<variable
…
name="handlers"
type="EventHandlers" />
<TextView
……
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CLICK ME"
android:onClick="@{handlers.click}"/>
binding.setHandler(new EventHandlers());
调用了EventHandlers里面的click(View view)方法。
- 数据的同步
@Bindable
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
notifyPropertyChanged(包名.BR.name);
}
在get方法上加上注释@Bindable
在set方法里面添加notifyPropertyChanged(包名.BR.name);
在点击事件中修改数据,数据就会自动修改了
public void click(View view) {
mStu.setName("ben");
}
}
ObservableFields家族
可以不需要定义get,set方法
数据类型定义为:
public ObservableField<String> name = new ObservableField<>();
public ObservableInt age = new ObservableInt();
Observable+基本数据类型的方式。- ObservableField
- ObservableBoolean
- ObservableByte
- ObservableShort
- ObservableInt
- ObservableLong
- ObservableDouble
- ObservableParcelable
- ObservableArrayMap
- ObservableArrayList
使用
mPeople = new People();
binding.setPeople(mPeople);
mPeople.name.set("people");
mPeople.age.set(19);
mPeople.isMan.set(true);
......
<variable
name="str"
type="android.databinding.ObservableField<String>" />
......
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{str.get}"/>
ObservableArrayMap<String, String> map = new ObservableArrayMap<>();
ObservableArrayList<String> list = new ObservableArrayList<>();
map.put("name", "abc");
list.add("hi");
binding.setMap(map);
binding.setList(list);
在fragment中使用
infate方法
MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater);
MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false);
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 包名.Custom binding = DataBindingUtil.inflate(inflater, R.layout.frag_layout, container, false); mStu = new Student(20, "abc"); //getRoot可以获取我们加载的布局 return binding.getRoot(); }
- RecyclerView的使用
private class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
private ArrayList<Student> mData = new ArrayList<>();
public MyAdapter(ArrayList<Student> data) {
mData = data;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//之前DataBindingUtil返回的那些都是ViewDataBinding的子类
ViewDataBinding binding=DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.recycler_view_item, parent, false);
//参数是item布局
ViewHolder holder=new ViewHolder(binding.getRoot());
//保存了刚刚返回的ViewDataBinding对象
holder.setBinding(binding);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.getBinding().setVariable(BR.stu, mData.get(position));
//当数据改变时,binding会在下一帧去改变数据,如果我们需要立即改变,就去调用executePendingBindings方法。
holder.getBinding().executePendingBindings();
}
@Override
public int getItemCount() {
return mData.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
private ViewDataBinding mBinding;
public ViewHolder(View itemView) {
super(itemView);
}
public void setBinding(ViewDataBinding binding) {
this.mBinding=binding;
}
public ViewDataBinding getBinding() {
return mBinding;
}
}
}
}
- 自定义setter
- ImageView需要通过网络去加载图片
- 格式化日期
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data class=".Custom">
<variable
name="imageUrl"
type="String" />
<variable
name="time"
type="java.util.Date" />
</data>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:image="@{imageUrl}"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{time}"/>
</layout>
java
binding.setImageUrl("https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/logo_white_fe6da1ec.png");
binding.setTime(new Date());
public class Utils {
//BindingAdapter 参数是控件中使用的自定义属性名称(image)
@BindingAdapter({"bind:image"})
public static void imageLoader(ImageView imageView, String url) {
Glide.with(imageView.getContext()).load(url).into(imageView);
}
//数据的转换
@BindingConversion
public static String convertDate(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(date);
}
}