月度归档:2016年09月

DataBinding的BR生成规则

生成的BR.class

package com.github.captain_miao.uniqueadapter.library;

public class BR {
    public static int _all = 0;
    public static int presenter = 1;
    public static int viewModel = 2;

    public BR() {
    }
}

从生成的规则上看,是通过变量名(viewModel/presenter)来生成ID的,所以相同的变量名共用相同的ID,所以使用相同的变量,可以减少ID哈。

也让UniqueAdapter成为可能,可以使用相同的ViewHolder。


@Override
public void onBindViewHolder(UniqueViewHolder holder, int position) {
    ItemModel item = getItem(position);
    holder.dataBinding.setVariable(com.github.captain_miao.uniqueadapter.library.BR.viewModel, item);
    if (mPresenter != null) {
        holder.dataBinding.setVariable(com.github.captain_miao.uniqueadapter.library.BR.presenter, mPresenter);
    }
    holder.dataBinding.executePendingBindings();
}

借助DataBinding,只需要一个Adapter。

背景

App有很多的List界面,每个界面都有不同的数据,然后都需要写个Adapter。当使用DataBinding之后,还是要写Adapter,但是需要写的内容越来越少。

/**
 * @author YanLu
 * @since 16/7/12
 */
public class DealerVehicleAdapter 
        extends BaseWrapperRecyclerAdapter<Vehicle, RecyclerView.ViewHolder> {
    private DealerVehiclePresenter mPresenter;

    public DealerVehicleAdapter(DealerVehiclePresenter presenter) {
        this.mPresenter = presenter;
    }


    @Override
    public RecyclerView.ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.rv_item_view_dealer_vehicle, parent, false);

        return new DealerVehicleAdapter.ViewHolder(view);
    }

    @Override
    public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
        final Vehicle vehicle = getItem(position);
        if(holder instanceof ViewHolder){
            ViewHolder viewHolder =(ViewHolder) holder;
            viewHolder.binding.setVariable(BR.viewModel, vehicle);
            viewHolder.binding.setVariable(BR.presenter, mPresenter);
            viewHolder.binding.executePendingBindings();
        }
    }


    public static class ViewHolder extends RecyclerView.ViewHolder {
        private ViewDataBinding binding;

        public ViewHolder(View itemView) {
            super(itemView);
            binding = DataBindingUtil.bind(itemView);
        }

        public ViewDataBinding getBinding() {
            return binding;
        }

    }

}

这个Adapter中,只做了两个事情:

1. ViewDataBinding创建

只需要一个参数:R.layout.rv_item_view

    @Override
    public RecyclerView.ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.rv_item_view_dealer_vehicle, parent, false);

        return new DealerVehicleAdapter.ViewHolder(view);
    }
2. DataBingding变量赋值

只需要二个参数:viewModel 和 presenter

    @Override
    public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
        final Vehicle vehicle = getItem(position);
        if(holder instanceof ViewHolder){
            ViewHolder viewHolder =(ViewHolder) holder;
            viewHolder.binding.setVariable(BR.viewModel, vehicle);
            viewHolder.binding.setVariable(BR.presenter, mPresenter);
            viewHolder.binding.executePendingBindings();
        }
    }
那能不能使用方提供layoutId、viewModel、presenter,就只需要一个Adapter呢?

实现

为了ItemModel不至于太多内容,presenter由Adapter自己提供,其他由ItemModel提供。

ItemModel
public interface ItemModel {
    // itemView layout
    int getItemViewLayoutId();
}
UniqueAdapter

由于要支持多种ItemViewType,直接使用ItemModel.getItemViewLayoutId(),全局唯一的。
如果要支持头部、尾部,可以使用负数来区分。

/**
 * @author YanLu
 * @since 16/7/12
 */
public class DealerVehicleAdapter 
        extends BaseWrapperRecyclerAdapter<Vehicle, RecyclerView.ViewHolder> {
    private DealerVehiclePresenter mPresenter;
 
    public DealerVehicleAdapter(DealerVehiclePresenter presenter) {
        this.mPresenter = presenter;
    }
 
 
    @Override
    public RecyclerView.ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.rv_item_view_dealer_vehicle, parent, false);
 
        return new DealerVehicleAdapter.ViewHolder(view);
    }
 
    @Override
    public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
        final Vehicle vehicle = getItem(position);
        if(holder instanceof ViewHolder){
            ViewHolder viewHolder =(ViewHolder) holder;
            viewHolder.getBinding().setVariable(BR.viewModel, vehicle);
            viewHolder.getBinding().setVariable(BR.presenter, mPresenter);
            viewHolder.getBinding().executePendingBindings();
        }
    }
 
 
    public static class ViewHolder extends RecyclerView.ViewHolder {
        private ViewDataBinding binding;
 
        public ViewHolder(View itemView) {
            super(itemView);
            binding = DataBindingUtil.bind(itemView);
        }
 
        public ViewDataBinding getBinding() {
            return binding;
        }
 
    }
 
}

兼容 旧的Adapter?

1. ItemModel很容易兼容,只需要implements ItemModel。
2. 旧的Adapter 继承 BaseUniqueAdapter

protected final List<? extends ItemModel> mDataList;


public UniqueAdapter(@NonNull List<? extends ItemModel> dataList) {
    this.mDataList = dataList;
}

public UniqueAdapter(@NonNull List<? extends ItemModel> dataList, UniquePresenter<? extends ItemModel> presenter) {
    this.mDataList = dataList;
    this.mPresenter = presenter;
}

public ItemModel getItem(int position) {
    return mDataList.get(position);
}

@Override
public int getItemCount() {
    return mDataList.size();
}

点击事件处理

android:onClick=”@{(v) -> presenter.onClick(v, viewModel)}”
这个至少可以满足80%的点击事件,不能满足的使用方自己定义哈。

public interface UniquePresenter<T extends ItemModel> extends Serializable {
    void onClick(View view, T t);
}


    // layout
    <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="@{(v) -> presenter.onClick(v, viewModel)}"
        >

GitHub地址

UniqueAdapter