入行幾個月了,一直想自己封裝一些類,剛好遇到了這個問題,現在跟大家分享。
注意點
1 泛型擦除
2 需要防止類型轉換異常
github地址:https://github.com/zw21544182/MyBaseDemo
(里面還有部分FileUtils常用相關方法),歡迎start 一起交流進步
關于RecyclerView.Adapter 一般的套路是這個樣子的
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//創建ViewHolder
return null;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//綁定數據
}
@Override
public int getItemCount() {
//獲取數據行數
return 0;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
//綁定Itme 中的View
super(itemView);
}
}
}
現在我想寫一個Adapter的基類
最初的想法是指定一個泛型,像這樣
public class MyRecyclerViewAdapter<T> extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
List<T> data;
Context context;
int layoutId;
public MyRecyclerViewAdapter(List<T> data, Context context, int layoutId) {
this.data = new ArrayList<>();
data.addAll(data);
this.context = context;
this.layoutId = layoutId;
}
//添加一些 setData clearData等方法
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//創建ViewHolder
View view = LayoutInflater.from(this.context).inflate(this.layoutId, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//綁定數據
}
@Override
public int getItemCount() {
//獲取數據行數
return data.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
//綁定Itme 中的View
super(itemView);
}
}
}
自我感覺這樣很完美,但是編譯通不過。報沒有實現子類onBindViewHolder的錯,額,好吧。就這樣,尷尬了一會,在網上查了查資料。后來想到為什么不直接泛型擦除呢?
最后就有了現在這個BaseRecyclerAdapter
/**
* 創建時間: 2017/11/29
* 創建人: Administrator
* 功能描述:RecyclerView基類(需要注意類型轉換問題)
*/
public abstract class BaseRecyclerViewAdapter extends RecyclerView.Adapter<BaseRecyclerViewAdapter.BaseViewHolder> {
protected ArrayList data;
protected Context context;
protected List<Integer> layoutIds;//布局集合
protected boolean isMore = true;//上拉刷新時,是否有更多數據
public BaseRecyclerViewAdapter(List data, Context context, List<Integer> layoutIds) {
this.data = new ArrayList<>();
this.layoutIds = new ArrayList<>();
this.data.addAll(data);
this.layoutIds.addAll(layoutIds);
this.context = context;
}
public void setData(List data) {
this.data.clear();
this.data.addAll(data);
notifyDataSetChanged();
}
public void clearAll() {
this.data.clear();
notifyDataSetChanged();
}
public Object getDataByPos(int index) {
if (data.size() <= index) {
return null;
}
return data.get(index);
}
public void addData(Object t) {
data.add(t);
notifyDataSetChanged();
}
public void addDatas(List data) {
this.data.addAll(data);
notifyDataSetChanged();
}
#重要 設置viewType
@Override
public int getItemViewType(int position) {
if (position + 1 == getItemCount()) {
return -1;//最后行時設為-1顯示footLayout
} else {
return position;//其他設為位置
}
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int pos) {
if (data.size() == 0) {//當data數據為0時
View view = LayoutInflater.from(context).inflate(R.layout.zwbase_no_data, parent, false);
//顯示暫無數據布局
return new BaseViewHolder(view);
}
if (pos == -1) {//pos為-1表示最后一行
View view = LayoutInflater.from(context).inflate(R.layout.zwbase_footlayout, parent, false);
//顯示底部布局
return new FootViewHolder(view);
}
int layout = getLayoutIdByPos(pos);
View view = LayoutInflater.from(context).inflate(layout, parent, false);
BaseViewHolder baseViewHolder = new BaseViewHolder(view);
clickView(baseViewHolder, data.get(pos), pos);
return baseViewHolder;
}
protected int getLayoutIdByPos(int pos) {
int res = 0;
if (pos < layoutIds.size()) {//layoutIds是存放布局的集合
res = layoutIds.get(pos);
} else {
res = layoutIds.get(pos % layoutIds.size());
}
return res;
}
/**
* 在oncreateViewHolder方法中設置點擊事件
* 避免重復調用
* @param baseViewHolder itme控件
* @param o itme 實體類
* @param pos 位置
*/
protected abstract void clickView(BaseViewHolder baseViewHolder, Object o, int pos);
protected abstract void setItmeData(BaseViewHolder baseViewHolder, Object itmeModule, int position) throws ClassCastException;
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
if (data.size() == 0) {
ImageView nodataImage = (ImageView) holder.getViewById(R.id.zwbase_imageview);
TextView nodataText = (TextView) holder.getViewById(R.id.zwbase_tvNoData);
setNodataInfo(nodataImage, nodataText);
return;
}
if (holder instanceof FootViewHolder) {
//判斷為底部布局時
if (isMore) {//再次判斷是否還有更多數據,加載相應的布局
holder.getViewById(R.id.loadmore).setVisibility(View.VISIBLE);
holder.getViewById(R.id.nodata).setVisibility(View.GONE);
} else {
holder.getViewById(R.id.loadmore).setVisibility(View.GONE);
holder.getViewById(R.id.nodata).setVisibility(View.VISIBLE);
}
return;
}
try {
setItmeData(holder, data.get(position), position);//設置顯示數據
} catch (ClassCastException e) {
e.printStackTrace();
}
}
protected void setNodataInfo(ImageView nodataImage, TextView nodataText) {
}
@Override
public int getItemCount() {
return data == null ? 0 : data.size() + 1;//數據為0或為空時返回0,否則data.size()+1
}
public void setMore(boolean more) {
//暴露方法給Activity
this.isMore = more;
}
protected class FootViewHolder extends BaseViewHolder {
public FootViewHolder(View itemView) {
super(itemView);
}
}
public class BaseViewHolder extends RecyclerView.ViewHolder {
//該類下部分方法可以自行添加
View rootView;
public BaseViewHolder(View itemView) {
super(itemView);
rootView = itemView;
}
public void setText(int viewId, int resourceId) {
((TextView) getViewById(viewId)).setText(resourceId);
}
public void setClickListent(int viewId, View.OnClickListener onClickListener) {
getViewById(viewId).setOnClickListener(onClickListener);
}
public void setText(int viewId, String content) {
((TextView) getViewById(viewId)).setText(content);
}
public void setCheckChangeListen(int viewId, CompoundButton.OnCheckedChangeListener onCheckedChangeListener) {
((CheckBox) getViewById(viewId)).setOnCheckedChangeListener(onCheckedChangeListener);
}
public void setImageSource(int imageViewId, int sourceId) {
ImageView imageView = (ImageView) getViewById(imageViewId);
imageView.setImageResource(sourceId);
}
public View getViewById(int viewId) {
return rootView.findViewById(viewId);
}
}
}
在打造我們自己的適配器時,我們可以繼承BaseRecyclerViewAdaPter
public class MyAdapter extends BaseRecyclerViewAdapter {
public MyAdapter(List data, Context context, List<Integer> layoutIds) {
super(data, context, layoutIds);
}
@Override
protected void clickView(BaseViewHolder baseViewHolder, Object o, int pos) {
}
@Override
protected void setItmeData(BaseViewHolder baseViewHolder, Object itmeModule, int position) throws ClassCastException {
int layoutNum = (position % layoutIds.size());
switch (layoutNum) {
case 0:
baseViewHolder.setText(R.id.tvText, (String) itmeModule);
break;
case 1:
baseViewHolder.setImageSource(R.id.ivImage, R.mipmap.image);
break;
}
}
}
在activity中傳入相關的布局Id號即可
data = new ArrayList<>();
layoutIds = new ArrayList<>();
layoutIds.add(R.layout.layout_rvitme);
layoutIds.add(R.layout.layout_image);
//需要注意的是layoutIds傳入的布局Id的順序和個數要與Adapter中的setItmeData對應
for (int i = 0; i < 100; i++) {
data.add("sssss " + i);
}
baseRecyclerViewAdapter = new MyAdapter(data, this, layoutIds);
myRview.setLayoutManager(new LinearLayoutManager(this));
myRview.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
myRview.setAdapter(baseRecyclerViewAdapter);
最后, 花了一些時間,封裝成了可刷新的view 下拉刷新用的官方+接口回調,上拉加載也是 可以去github上看看,一起交流學習