當項目當中遇到了很多個頁面都要用到清單的時候,我們可能會用到ListView又或者用到RecyclerView,其實不管用到哪個控件來實作,adapter和hodler是必須要用到的,每寫一個ListView或者RecyclerView,都要去實作一個adapter和hodler,顯然有很多重複的代碼,那麼能不能把共有的方法抽取出來呢,顯然是可以的,ListView的抽取以前寫過,位址是: http://blog.csdn.net/ming_147/article/details/62892727,這邊文章主要是叙述RecyclerView的抽取。
RecyclerView的Adapter是繼承于RecyclerView.Adapter<BaseAdapter.ViewHolder>,ViewHolder在這裡我是以泛型的形式引入進來,并在BaseAdapter類中具體實作,如下:
public class BaseAdapter extends RecyclerView.Adapter<BaseAdapter.ViewHolder>{
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
}
}
好了,具體就這些方法,那麼該如何去下手呢,我們可以先分析一下,要實作一個Adapter,我們都需要哪些條件呢?首先資料是必不可少的,一般是以集合的形式傳入,這裡我們可以從構造方法裡傳進,集合确定,而類型不能确定,我們可以用D來辨別,執行個體變量攜帶泛型,記得給類也加上泛型,這裡我寫了一個空的接口,用來做雙向綁定,如下:
public class BaseAdapter<D extends IModel> extends RecyclerView.Adapter<BaseAdapter.ViewHolder> {
private List<D> dataList;
public BaseAdapter(List<D> dataList) {
this.dataList = dataList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return dataList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
}
}
資料傳入了,那麼還少什麼呢,對,View視圖,這裡我把BaseAdapter改成了抽象類,并實作擷取view的一個抽象方法,并在onCreateViewHolder方法裡進行使用,如下:
public abstract int getLayoutId();
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(getLayoutId(),parent,false);
BaseAdapter.ViewHolder vh = new BaseAdapter.ViewHolder(view);
return vh;
}
接下來,就是向外繼續抽象一個方法,用于資料的綁定,其實就是把onBindViewHolder方法,抽象到外面自己來實作其裡面的功能:
public abstract void createHolder(BaseAdapter.ViewHolder holder, D d);
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
createHolder(holder,dataList.get(position));
}
目前為止,adapter裡已經抽取完成,下面看下ViewHolder裡,其實在ViewHolder裡,主要用于擷取控件:
public static class ViewHolder extends RecyclerView.ViewHolder {
private View rootView;
private SparseArray<View> views=new SparseArray<>();
public ViewHolder(View itemView) {
super(itemView);
}
public <T extends View> T get(int id){
T view=(T)views.get(id);
if(view==null){
view=(T)rootView.findViewById(id);
views.put(id,view);
}
return view;
}
//TextView設定資料
public void setText(int viewId, String txt) {
TextView mTextView = get(viewId);
mTextView.setText(txt);
}
//設定圖檔
public void setPic(int viewId, String url) {
ImageView mImageView = get(viewId);
Picasso.with(mContext).load(url).fit().error(R.drawable.ic_launcher).placeholder(mImageView.getDrawable()).memoryPolicy(MemoryPolicy.NO_CACHE).into(mImageView);
}
}
這裡我寫了兩個方法setText和setPic,主要目的就是簡便我們的代碼,友善我們調用,到這裡,我們這個BaseAdapter,已經抽取完成了,下面看一下整個類:
/**
* Created by AbnerMing on 2017/12/29.
*/
public abstract class BaseAdapter<D extends IModel> extends RecyclerView.Adapter<BaseAdapter.ViewHolder> {
private List<D> dataList;
public abstract int getLayoutId();
public BaseAdapter(List<D> dataList) {
this.dataList = dataList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(getLayoutId(),parent,false);
BaseAdapter.ViewHolder vh = new BaseAdapter.ViewHolder(view);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
createHolder(holder,dataList.get(position));
}
@Override
public int getItemCount() {
return dataList.size();
}
public abstract void createHolder(BaseAdapter.ViewHolder holder, D d);
public static class ViewHolder extends RecyclerView.ViewHolder {
private View rootView;
private SparseArray<View> views=new SparseArray<>();
public ViewHolder(View itemView) {
super(itemView);
}
public <T extends View> T get(int id){
T view=(T)views.get(id);
if(view==null){
view=(T)rootView.findViewById(id);
views.put(id,view);
}
return view;
}
//TextView設定資料
public void setText(int viewId, String txt) {
TextView mTextView = get(viewId);
mTextView.setText(txt);
}
//設定圖檔
public void setPic(int viewId, String url) {
ImageView mImageView = get(viewId);
Picasso.with(mContext).load(url).fit().error(R.drawable.ic_launcher).placeholder(mImageView.getDrawable()).memoryPolicy(MemoryPolicy.NO_CACHE).into(mImageView);
}
}
}
具體調用:
public class MyAdapter extends BaseAdapter<Bean>{
public MyAdapter(List<Bean> dataList) {
super(dataList);
}
@Override
public int getLayoutId() {
return 0;
}
@Override
public void createHolder(BaseAdapter.ViewHolder holder, Bean bean) {
}
}
以後所有的Adapter都可以去繼承BaseAdapter,隻僅僅的實作兩個方法就ok了,是不是友善多了。