您的位置:首页 > 其它

为RecyclerView打造简单易用扩展性高的万能适配器

2016-12-21 10:32 721 查看
相信用listview开发的过程当中我们肯定用过各类万能的Adapter适配器,当我们迁移到使用Recycleview的开发中会发现虽然它的功能比listview强大不少,但是代码写起来还是略显麻烦了些,于是我们感觉也要使用一个简单易用的万能适配器来写代码,前段时候受到了一篇博客的启发,感觉实现的还是不够简洁和扩展性强,于是想到了一种封装方式,写一个万能适配器,让大家使用。

下面我们直奔主题讲解一下思路,首先我们想到的是把Adapter和viewholder分离开两个类来实现,这样做的好处是降低了代码的耦合,思路更加的清晰:

public abstract class BaseRecyclerAdapter<T>  extends RecyclerView.Adapter<RecyclerHolder> {

protected List<T> dataSources;
protected Context mContext;
protected final int mItemLayoutId;
private OnItemClickListener listener;
private OnItemLongClickListener longlistener;

public BaseRecyclerAdapter(RecyclerView v, Collection<T> datas, int itemLayoutId) {
if (datas == null) {
dataSources = new ArrayList<>();
} else if (datas instanceof List) {
dataSources = (List<T>) datas;
} else {
dataSources = new ArrayList<>(datas);
}
this.mContext=v.getContext();
this.mItemLayoutId=itemLayoutId;
}

@Override
public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.e("测试","onCreateViewHolder");
View root = LayoutInflater.from(mContext).inflate(mItemLayoutId, parent, false);
return new RecyclerHolder(root);
}

@Override
public void onBindViewHolder(RecyclerHolder holder, int position) {
Log.e("测试","onBindViewHolder"+position);
convert(holder, dataSources.get(position), position);
holder.itemView.setOnClickListener(getitemviewOnClickListener(position));
holder.itemView.setOnLongClickListener(getitemviewOnLongClickListener(position));
}

/**
* 让子类实现的抽象方法
* @param holder  holder
* @param item    一般是实体bean对象
* @param position  item的位置
*/
public abstract void convert(RecyclerHolder holder, T item, int position);

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

public View.OnClickListener getitemviewOnClickListener(final int position) {
return new View.OnClickListener() {
@Override
public void onClick(@Nullable View v) {
if (listener != null && v != null) {
listener.onItemClick(v, dataSources.get(position), position);//回调
}
}
};
}
public View.OnLongClickListener getitemviewOnLongClickListener(final int position) {
return new View.OnLongClickListener(){
@Override
public boolean onLongClick(View v) {
if (listener != null && v != null) {
longlistener.onItemLongClick(v, dataSources.get(position), position);//回调
}
return true;
}
};
}

//--------------类似的方法根据自己需求自己添加-------------------------------------
public interface OnItemClickListener {
void onItemClick(View view, Object data, int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}
public interface OnItemLongClickListener {
void onItemLongClick(View view, Object data, int position);
}
public void setOnItemLongClickListener(OnItemLongClickListener longlistener) {
this.longlistener = longlistener;
}
}


在构造方法当中我传入了recycleview对象,集合对象以及布局的id,通过recycleview对象我们可以获得上下文对象,为什么这里不是直接传入context对象呢,因为这样做的目的是增加适配器的扩展性,通过这个recycleview对象我们还可以添加很多有用的方法,比如说调用addOnScrollListener方法可以获取recycleveiw滑动的距离,这个时候你可以在下面继续添加接口回调来实现自己的需要等等,传入布局的id更方便了我们只需关注赋值操作就可以。

public class RecyclerHolder extends RecyclerView.ViewHolder {
private SparseArray<View> mViews;//集合类,以view的id作为key,value是view对象(SparseArray比HashMap更省内存,只能存储key为int类型的数据)
public RecyclerHolder(View itemView) {
super(itemView);
this.mViews=new SparseArray<View>();
}

/**
* 这种写法代替用findViewById的写法来保存引用在holder对象当中,用SparseArray集合来保存对象引用
* @param viewId  控件的id
* @param <T>
* @return
*/
public <T extends View> T getView(int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = itemView.findViewById(viewId);//itemView在构造方法传进去了
mViews.put(viewId, view);
}
return (T) view;
}
/**
* 为TextView设置字符串
*
* @param viewId
* @param text
* @return
*/
public RecyclerHolder setText(int viewId, String text) {
TextView view = getView(viewId);
view.setText(text);
return this;
}
/**
* 为ImageView设置图片
*
* @param viewId
* @param drawableId
* @return
*/
public RecyclerHolder setImageResource(int viewId, int drawableId) {
ImageView view = getView(viewId);
view.setImageResource(drawableId);
return this;
}
/**
* 为ImageView设置图片,设置加载时图片
*
* @param viewId
* @param url
* @return
*/
public RecyclerHolder setImageResource(int viewId, String url) {
ImageView view = getView(viewId);
Glide.with(view.getContext()).load(url).into(view);
return this;
}
/**
*
*
* 类似的方法根据自己需求自己添加
*
*
*/
}


在holder当中处理的更加简洁明了 ,我们可以随意的添加我们自己的需求并且使用任意的图片加载框架,不想使用Glide,我们就把他替换成picasso,是不是感觉很简单,哈哈。

使用更简单:

LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
rvContent.setLayoutManager(layoutManager);
adapter = new ExampleAdapter(rvContent, meizis, R.layout.item_layout);
rvContent.setAdapter(adapter);


public class ExampleAdapter  extends BaseRecyclerAdapter<Meizi> {
public ExampleAdapter(RecyclerView v, Collection<Meizi> datas, int itemLayoutId) {
super(v, datas, itemLayoutId);
}

@Override
public void convert(RecyclerHolder holder, Meizi item, int position) {
holder.setImageResource(R.id.iv_item,item.getUrl());
holder.setText(R.id.tv_item,item.getWho());
}
}


Demo地址: BaseRecyclerViewDemo
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: