DataBinding的基础使用
将.xml文件转为DataBinding的文件,会出现一个<data>的标签,在其中可以定义变量<variables>或导入<import>:
<data>
<variable
name="idol"
type="com.shopkeeper.databinding.Idol" />
<import type="com.shopkeeper.databinding.StarUtils" />
<variable
name="eventHandler"
type="com.shopkeeper.databinding.EventHandleListener" />
</data>在绑定数据时,使用@{}语法:
<TextView
android:text="@{idol.name}"/>
<TextView
android:text="@{StarUtils.getDarling(idol.star)}"/>在绑定事件的监听时,以onClick为例,可以使用@{}传入一个方法:
<Button
android:onClick="@{eventHandler.btnOnClick}"/>该方法会传入一个View的实例
public class EventHandleListener {
private Context context;
public EventHandleListener(Context context) {
this.context = context;
}
public void btnOnClick(View view){
Toast.makeText(context,"like 02",Toast.LENGTH_SHORT).show();
}
}也可以绑定一个监听器(可以传入任意参数),以一个viewModel的add方法为例:
<Button
android:onClick="@{()->viewModel.add()}"/>对include的组件进行数据绑定
需要使用app命名空间传入该变量名。例如sub.xml定义的一个variable是idol:
<data>
<variable
name="idol"
type="com.shopkeeper.databinding2.Idol" />
<import type="com.shopkeeper.databinding2.StarUtils"/>
</data>那么在include其的main.xml中,使用app:idol传入其需要的变量:
<include
layout="@layout/sub"
app:idol="@{idol}"
>使用BaseAdapter对不可直接绑定的组件绑定数据
以ImageView为例,显示图片时需要使用到glide,因此可以定义一个类,用@BindingAdapter来注解用于处理图片的方法:
public class IVBindingAdapter {
@BindingAdapter("image")
public static void setImage(ImageView imageView,String url){
if (!TextUtils.isEmpty(url)){
Glide.with(imageView)
.load(url)
.into(imageView);
}
}
}@BindingAdapter括号内的字符串即是在ImageView组件中需要使用的属性(用法类似include传参),例如此时括号内定义的value是”image”,那么在ImageView中需要传入image属性:
<ImageView
android:id="@+id/imageView"
app:image="@{networkImage}" />由于value可以传入一个数组
因此可以传入多个参数,并通过requireAll来配置是否需要全部传入:
public class IVBindingAdapter {
@BindingAdapter(value = {"image","default_image"},requireAll = false)
public static void setImage(ImageView imageView,String url,int res){
if (!TextUtils.isEmpty(url)){
Glide.with(imageView)
.load(url)
.placeholder(R.drawable.ic_launcher_background)
.into(imageView);
}else {
Glide.with(imageView)
.load(res)
.placeholder(R.drawable.ic_launcher_background)
.into(imageView); }
}
}在xml中也需要传入这两个参数:
<ImageView
android:id="@+id/imageView"
app:image="@{networkImage}"
app:default_image="@{localImage}" />使用BaseObservable进行双向绑定
自定义一个继承于BaseObservable的ViewModel(并不是Jetpack的ViewModel类),可用于双向绑定,具体做法如下:
想要绑定一个数据,就需要在其get方法中用@Bindable注解:
private User user;
@Bindable
public String getUserName(){
return user.userName;
}在对其进行修改的时候,需要调用notifyPropertyChanged以声明其已经改变:
public void setUserName(String name){
if (!TextUtils.isEmpty(name)&&!name.equals(user.userName)){
user.userName=name;
Log.d("shopkeeperTag", "setUserName: "+name);
// BR是用Bindable注解标记的量,且必须是getXXX
notifyPropertyChanged(BR.userName);
}
}在xml中进行数据的双向绑定时,需要使用@={}语法:
<EditText
android:text="@={viewModel.userName}" />使用ObservableField进行双向绑定
ObservableField的使用类似于LiveData:
private ObservableField<User> userObservableField;此时,只需要定义需要绑定的变量的setter和getter方法之后,并在xml中使用@={}语法,就能完成双向绑定:
public String getUserName(){
return userObservableField.get().userName;
}
public void setUserName(String userName){
Log.d("shopkeeperTag", "setUserName: "+userName);
userObservableField.get().setUserName(userName);
}此方法的一个弊端是,必须使用setter方法来对数据进行修改,否则更改不会应用到视图上。
对RecyclerView进行数据绑定
本质上就是在RecyclerView.Adapter中对每一个Item进行数据绑定,onCreateViewHolder中返回的是通过item的DataBinding的实例创建出来的组件对象;onBindViewHolder中对item的DataBinding实例设置了数据。
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
List<Idol> idols;
public RecyclerViewAdapter(List<Idol> idols) {
this.idols = idols;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemBinding binding=DataBindingUtil.inflate(LayoutInflater.from(parent.getContext())
,R.layout.item,parent,false);
return new MyViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
Idol idol=idols.get(position);
holder.binding.setIdol(idol);
}
@Override
public int getItemCount() {
return idols.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder{
private ItemBinding binding;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
}
public MyViewHolder(@NonNull ItemBinding binding) {
super(binding.getRoot());
this.binding=binding;
}
}
}结合ViewModel和LiveData使用
用法与ObservableField类似,只不过不需要专门设置getter和setter,直接在xml中进行绑定livedata对象即可。