DataBinding(二)
1. 列表绑定
以RecyclerView为例,主要变化在子项布局和适配器。
1. 将子项布局改为DataBinding布局
public class Dishes {
private String imgAdress;
private String name;
public Dishes(String imgAdress, String name) {
this.imgAdress = imgAdress;
this.name = name;
}
public String getImgAdress() {
return imgAdress;
}
public void setImgAdress(String imgAdress) {
this.imgAdress = imgAdress;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.card.MaterialCardView
android:id="@+id/item_cv"
android:layout_marginTop="5dp"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_marginBottom="5dp"
app:cardCornerRadius="10dp"
app:cardElevation="5dp"
android:layout_width="match_parent"
android:layout_height="225dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/id_dishes_img"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginLeft="8dp"
android:layout_gravity="center_vertical"
android:layout_width="200dp"
android:layout_height="200dp"
android:scaleType="centerCrop"
app:imageUrl="@{dishes.imgAdress}"/>
<TextView
android:id="@+id/id_dishes_title"
android:layout_marginLeft="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/id_dishes_img"
app:layout_constraintVertical_bias="0.3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{dishes.name}"
android:textStyle="bold"
android:textSize="28sp"
android:lines="2" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</layout>
布局中设置一个CardView,包含一个TextView和一个ImageView
2. 适配器
适配器的改变主要在ViewHolder。
public class DishesAdapter extends RecyclerView.Adapter<DishesAdapter.BindingViewHolder>{
private DishesClickListener listener;
private LayoutInflater inflater;
private List<Dishes> list;
public DishesAdapter(Context context) {
inflater = LayoutInflater.from(context);
list = new ArrayList<>();
}
static class BindingViewHolder<T extends ViewDataBinding>
extends RecyclerView.ViewHolder{
private T binding;
public BindingViewHolder(T binding) {
super(binding.getRoot());
this.binding=binding;
}
public T getBinding() {
return binding;
}
}
@NonNull
@Override
public BindingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ViewDataBinding binding;
binding = DataBindingUtil.inflate(inflater, R.layout.dishes_list_item,parent,false);
return new BindingViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull BindingViewHolder holder, int position) {
Dishes dishes = list.get(position);
ViewDataBinding binding = holder.getBinding();
binding.setVariable(BR.dishes,dishes);
binding.executePendingBindings();
holder.itemView.setOnClickListener(v -> listener.onClick(dishes));
}
public void addAll(List<Dishes> dishes){
list.addAll(dishes);
}
@Override
public int getItemCount() {
return list.size();
}
public void setListener(DishesClickListener listener){
this.listener = listener;
}
public interface DishesClickListener{
void onClick(Dishes dishes);
}
}
之前的RecyclerView的适配器,ViewHolder中有布局中的控件,现在我们结合DataBinding,ViewHolder中只需要有ViewDataBinding,再通过ViewDataBinding将数据set到布局中去。
onCreateViewHolder()
这行代码binding = DataBindingUtil.inflate(inflater, R.layout.dishes_list_item,parent,false);
相当于原来View = inflater.inflate(R.layout.dishes_list_item,parent,false);
不同的是,会返回一个ViewDataBinding
onBindViewHolder()
ViewDataBinding binding = holder.getBinding();
binding.setVariable(BR.dishes,dishes);
首先获取ViewDataBinding,然后将数据set进去。
binding.executePendingBindings();
对数据做一个及时的刷新。
2. 自定义属性
- @BindingAdapter
<ImageView
android:id="@+id/id_dishes_img"
android:layout_width="200dp"
android:layout_height="200dp"
android:scaleType="centerCrop"
app:imageUrl="@{}"/>
@BindingAdapter("imageUrl")
public static void setImageUrl(ImageView imageView,String url){
Glide.with(imageView).load(Uri.parse(url)).into(imageView);
}
当用@BindingAdapter注解方法时,该方法必须声明为 public static
参数:第一个是绑定的控件,第二个参数就是可传来的自定义参数。
多参数
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/id_xuri_rv"
app:adapter="@{adapter}"
app:layoutManager="@{manager}"/>
@BindingAdapter(value = {"adapter","layoutManager"})
public static void setAdapterAndManager(RecyclerView recyclerView, DishesAdapter adapter, RecyclerView.LayoutManager manager){
recyclerView.setLayoutManager(manager);
recyclerView.setAdapter(adapter);
}
@BindingAdapter(value = {"adapter","layoutManager"},requireAll = false)
public static void setAdapterAndManager(RecyclerView recyclerView, DishesAdapter adapter, RecyclerView.LayoutManager manager){
recyclerView.setLayoutManager(manager);
recyclerView.setAdapter(adapter);
}
当设置requireAll为false时,说明在xml文件中不是必须两个参数都要设置。
- @BindingConversion
这个注解主要是对属性类型的转换
<View
android:background="@{@color/red}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
@BindingConversion
public static ColorDrawable convertColorToDrawable(int color){
return new ColorDrawable(color);
}
这样就会对@color/red进行类型转换,该方法也必须声明为 public static