
打造一个通用的Adapter,可以减少我们的代码量,通用的Adapter需要我们考虑三个问题:
- 数据的类型?我们可以采用泛型;
- 布局?我们可以利用构造函数传递;
- 绑定?利用回传,让子类实现;
1.Adapter的基本改造
通用Adapter的代码如下:
public abstract class CommonRecyclerAdapter<T> extends RecyclerView.Adapter<ViewHolder> {
protected Context mContext;
protected LayoutInflater mInflater;
protected List<T> mDatas;
private int mLayoutId;
public CommonRecyclerAdapter(Context context, List<T> datas, int layoutId) {
this.mContext = context;
this.mInflater = LayoutInflater.from(mContext);
this.mDatas = datas;
this.mLayoutId = layoutId;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = mInflater.inflate(mLayoutId, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (mDatas != null){
convert(holder, mDatas.get(position),position);
}else {
convert(holder, null,position);
}
}
/**
* 利用抽象方法回传出去,每个不一样的Adapter去设置
* @param item 当前的数据
*/
public abstract void convert(ViewHolder holder, T item,int position);
@Override
public int getItemCount() {
return mDatas == null ? 20:mDatas.size();
}
}
实际使用如下:
public class TestAdapter extends CommonRecyclerAdapter<String> {
public TestAdapter(Context context, List<String> datas) {
super(context,datas,R.layout.item_demo);
}
@Override
public void convert(ViewHolder viewHolder, String bean, int position) {
TextView text = (TextView)viewHolder.itemView.findViewById(R.id.tv_text);
text.setText(String.format("第%d数据", position + 1));
}
}
可以看到代码量大大滴减少了。
但是上面使用中我们发现每次调用onBindViewHolder都会findViewById,所以我们还需要对ViewHolder进行优化。
2.ViewHolder的优化
优化后的ViewHolder如下:
public class ViewHolder extends RecyclerView.ViewHolder {
//用来存放view减少findviewByid的次数
private SparseArray<View> mViews;
public ViewHolder(@NonNull View itemView) {
super(itemView);
mViews = new SparseArray<>();
}
/**
* 设置TextView文本
* @param viewId
* @param text
* @return
*/
public ViewHolder setText(int viewId,CharSequence text){
TextView tv = getView(viewId);
tv.setText(text);
return this;
}
public <T extends View> T getView(int viewId){
View view = mViews.get(viewId);
if (view == null){
view = itemView.findViewById(viewId);
mViews.put(viewId,view);
}
return (T)view;
}
/**
* 设置view是否可见
* @param viewId
* @param visibility
* @return
*/
public ViewHolder setViewVisibility(int viewId,int visibility){
getView(viewId).setVisibility(visibility);
return this;
}
/**
* 设置ImageView资源
* @param viewId
* @param resId
* @return
*/
public ViewHolder setImageResourse(int viewId,int resId){
ImageView imageView = getView(viewId);
imageView.setImageResource(resId);
return this;
}
/**
* 设置条目的点击事件
* @param listener
*/
public void setOnItemClickListener(View.OnClickListener listener){
itemView.setOnClickListener(listener);
}
/**
* 设置图片通过url,加载图片使用的第三方可能不一样,所以定义了HolderImageLoader
* @param viewId
* @param imageLoader
*/
public void setImageByUrl(int viewId,HolderImageLoader imageLoader){
ImageView imageView = getView(viewId);
if (imageLoader == null){
throw new NullPointerException("imageLoader is null!");
}
imageLoader.displayImage(imageView.getContext(),imageView,imageLoader.getImagePath());
}
/**
* 设置条目的长按事件
* @param listener
*/
public void setOnItemLongClickListener(View.OnLongClickListener listener){
itemView.setOnLongClickListener(listener);
}
public static abstract class HolderImageLoader{
private String mImagePath;
public HolderImageLoader(String imagePath){
this.mImagePath = imagePath;
}
public String getImagePath(){
return mImagePath;
}
public abstract void displayImage(Context context,ImageView imageView,String imagePath);
}
}
实际使用:
public class TestAdapter extends CommonRecyclerAdapter<String> {
public TestAdapter(Context context, List<String> datas) {
super(context,datas,R.layout.item_demo);
}
@Override
public void convert(ViewHolder viewHolder, String bean, int position) {
viewHolder.setText(R.id.tv_text,String.format("第%d数据", position + 1))
}
}
3.多布局的实现
public interface MultiTypeSupport<T> {
public int getLayoutId(T bean,int position);
}
最终的Adapter:
public abstract class CommonRecyclerAdapter<T> extends RecyclerView.Adapter<ViewHolder> {
protected Context mContext;
protected LayoutInflater mInflater;
protected List<T> mDatas;
private int mLayoutId;
//多布局支持
private MultiTypeSupport mMultiTypeSupport;
public CommonRecyclerAdapter(Context context, List<T> datas, int layoutId) {
this.mContext = context;
this.mInflater = LayoutInflater.from(mContext);
this.mDatas = datas;
this.mLayoutId = layoutId;
}
//多布局支持
public CommonRecyclerAdapter(Context context, List<T> datas, MultiTypeSupport multiTypeSupport) {
this(context, datas, -1);
mMultiTypeSupport = multiTypeSupport;
}
@Override
public int getItemViewType(int position) {
if (mMultiTypeSupport != null)
return mMultiTypeSupport.getLayoutId(mDatas.get(position), position);
return super.getItemViewType(position);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mMultiTypeSupport != null)
mLayoutId = viewType;
View itemView = mInflater.inflate(mLayoutId, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
if (mItemClickListener != null) {
holder.setOnItemClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mItemClickListener.OnItemClick(position);
}
});
}
if (mLongClickListener != null) {
holder.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
return mLongClickListener.onLongClick(position);
}
});
}
if (mDatas != null) {
convert(holder, mDatas.get(position), position);
} else {
convert(holder, null, position);
}
}
/**
* 利用抽象方法回传出去,每个不一样的Adapter去设置
*
* @param item 当前的数据
*/
public abstract void convert(ViewHolder holder, T item, int position);
@Override
public int getItemCount() {
return mDatas == null ? 20 : mDatas.size();
}
/***************
* 设置条目点击和长按事件
*********************/
public OnItemClickListener mItemClickListener;
public OnLongClickListener mLongClickListener;
public void setOnItemClickListener(OnItemClickListener itemClickListener) {
this.mItemClickListener = itemClickListener;
}
public void setOnLongClickListener(OnLongClickListener longClickListener) {
this.mLongClickListener = longClickListener;
}
public interface OnItemClickListener {
void OnItemClick(int position);
}
public interface OnLongClickListener {
boolean onLongClick(int position);
}
}
网友评论