打造listview通用的Adapter
2017-11-06 本文已影响15人
AJI大侠
叙述
1.在Android开发中写Adapter是一件枯燥重复的工作。 对于Adapter一般都继承BaseAdapter写几个方法,getView里面用ViewHolder存储,这里我做一次Adapter封装,打造一个通用的Adapter,想写下来也是为了方便日后的查看,当然这里我们不谈
RecyclerView
下面是一段常用写法,每次都写到我想吐,一看到列表就想起了BaseAdapter - -!
public class HomeAdapter extends BaseAdapter
{
private Context mContext;
private List<HomeBean> homeBeanList;
private LayoutInflater layoutInflater;
public HomeAdapter(Context mContext, List<HomeBean> homeBeanList)
{
this.layoutInflater = LayoutInflater.from(mContext);
this.mContext = mContext;
this.homeBeanList = homeBeanList;
}
@Override
public int getCount()
{
if(homeBeanList == null || homeBeanList.size() <= 0)
{
return 0;
}
return homeBeanList.size();
}
@Override
public Object getItem(int position)
{
return homeBeanList.get(position);
}
@Override
public long getItemId(int position)
{
return position;
}
public void refresh(List<HomeBean> datas)
{
if (datas == null)
{
datas = new ArrayList<>(0);
}
this.homeBeanList = datas;
notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHodler viewHodler = null;
HomeBean homeBean = homeBeanList.get(position);
if (convertView == null)
{
viewHodler = new ViewHodler();
convertView = layoutInflater.inflate(R.layout.home_item , parent , false);
viewHodler.home_item_icon = convertView.findViewById(R.id.home_item_icon);
viewHodler.home_item_text = convertView.findViewById(R.id.home_item_text);
viewHodler.home_item_price = convertView.findViewById(R.id.home_item_price);
convertView.setTag(viewHodler);
}
else
{
viewHodler = (ViewHodler) convertView.getTag();
}
ImageLoadUtils.loadImage(mContext , homeBean.getImageUrl().getUrl() , viewHodler.home_item_icon);
viewHodler.home_item_text.setText(homeBean.getTitle());
viewHodler.home_item_price.setText(homeBean.getPrice());
return convertView;
}
public static class ViewHodler
{
private TextView home_item_text;
private TextView home_item_price;
private ImageView home_item_icon;
}
}
- 这一种写法相信大家都写的很熟了,我就不多说了下面我们看看如何写通用的adapter
1.新建一个class,写好通用的HodlerView,代码如下
public class FuHodlerView
{
private final SparseArray<View> mViews;
private final int mPositiom;
private final View mConvertView;
public FuHodlerView(ViewGroup parent , int layoutId , int position)
{
this.mPositiom = position;
mViews = new SparseArray<>();
mConvertView = LayoutInflater.from(parent.getContext()).inflate(layoutId , parent , false);
// setTag()
mConvertView.setTag(this);
}
/**
* 拿到全部的views
* @return
*/
public SparseArray<View> getAllViews()
{
return mViews;
}
/**
* 拿到一个viewHodler对象
* @param convertView
* @param parent
* @param layoutId
* @param position
* @return
*/
public static FuHodlerView get(View convertView , ViewGroup parent , int layoutId , int position)
{
if(convertView == null)
{
return new FuHodlerView(parent , layoutId ,position);
}
else
{
return (FuHodlerView) convertView.getTag();
}
}
public View getConvertView()
{
return mConvertView;
}
/**
* 通过控件的Id获取对于的控件,如果没有则加入views
* @param viewId
* @param <T>
* @return
*/
public <T extends View> T getView(int viewId)
{
View view = mViews.get(viewId);
if(view == null)
{
view = mConvertView.findViewById(viewId);
}
mViews.put(viewId , view);
return (T) view;
}
/**
* 为TextView设置字符串
* @param viewId
* @param text
* @return
*/
public FuHodlerView setText(int viewId , CharSequence text)
{
TextView textView = getView(viewId);
textView.setText(text);
return this;
}
/**
* 为Imageview设置本地图片
* @param viewId
* @param drawableId
* @return
*/
public FuHodlerView setImageResource(int viewId , int drawableId)
{
ImageView imageView = getView(viewId);
imageView.setImageResource(drawableId);
return this;
}
/**
* 为Imageview设置网络图片
* @param viewId
* @param url
* @return
*/
public FuHodlerView setImageByUrl(Context context ,int viewId , String url)
{
ImageView imageView = getView(viewId);
ImageLoadUtils.loadImage(context , url , imageView);
return this;
}
public int getPositiom()
{
return mPositiom;
}
}
-代码注释的很清楚,大家可以自己看,我主要说的是这里用到了-SparseArray缓存我们itemView内部的子View,这样可以得到一个通用的ViewHolder,每次要创建ViewHolder的时候只需要传入我们的layoutId即可。
2.有了ViewHolder,下面我们就可以打造通用的adapter了,代码如下:
public abstract class FuBaseAdapter<T> extends BaseAdapter implements AbsListView.OnScrollListener
{
protected Collection<T> mDatas;
private final int mItemLayoutId;
private AbsListView mListView;
// 是否在滑动
private boolean isScrolling;
private Context mContext;
private LayoutInflater inflater;
private AbsListView.OnScrollListener listener;
public FuBaseAdapter(AbsListView listView , Collection<T> mDatas , int mItemLayoutId)
{
if(mDatas == null)
{
mDatas = new ArrayList<>(0);
}
this.mDatas = mDatas;
this.mListView = listView;
this.mItemLayoutId = mItemLayoutId;
mContext = listView.getContext();
inflater = LayoutInflater.from(mContext);
mListView.setOnScrollListener(this);
}
// 刷新数据
public void refresh(Collection<T> mDatas)
{
if(mDatas == null)
{
mDatas = new ArrayList<>(0);
}
this.mDatas = mDatas;
notifyDataSetChanged();
}
public void addOnScrollListener(AbsListView.OnScrollListener l)
{
this.listener = l;
}
@Override
public int getCount()
{
if (mDatas == null || mDatas.size() <= 0)
{
return 0;
}
return mDatas.size();
}
@Override
public T getItem(int position)
{
if (mDatas instanceof List)
{
return ((List<T>) mDatas).get(position);
}
else if (mDatas instanceof Set)
{
return new ArrayList<T>(mDatas).get(position);
}
else
{
return null;
}
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
final FuHodlerView fuHodlerView = getViewHodler(position , convertView ,parent);
convert(fuHodlerView , getItem(position) , isScrolling ,position);
return fuHodlerView.getConvertView();
}
public FuHodlerView getViewHodler(int position , View convertView , ViewGroup parent)
{
return FuHodlerView.get(convertView , parent , mItemLayoutId , position);
}
public void convert(FuHodlerView helper , T item , boolean isScrolling)
{
}
public void convert(FuHodlerView helper , T item , boolean isScrolling , int position)
{
convert(helper, getItem(position), isScrolling);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState)
{
// 当前没有滚动的时候
if(scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE)
{
isScrolling = false;
this.notifyDataSetChanged();
}
else
{
isScrolling = true;
}
if(listener != null)
{
listener.onScrollStateChanged(view , scrollState);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
if(listener != null)
{
listener.onScroll(view , firstVisibleItem , visibleItemCount , totalItemCount);
}
}
}
-在这里我继承了OnScrollListener,这里主要是为了做一个优化即滚动时不加载图片
3.最关键的时候到了,怎使用呢只需继承我们通用的Adapter,请看代码,代码是最好的老师
public class HomeFuAdapter extends FuBaseAdapter<HomeBean>
{
public HomeFuAdapter(AbsListView listView, List<HomeBean> mDatas)
{
super(listView, mDatas, R.layout.home_item);
}
@Override
public void convert(FuHodlerView helper, HomeBean item, boolean isScrolling)
{
Context context = helper.getConvertView().getContext();
if(isScrolling)
{
ImageView imageView = helper.getView(R.id.home_item_icon);
ImageLoadUtils.loadImage(context , item.getImageUrl().getUrl() ,imageView);
}
else
{
helper.setImageByUrl(context , R.id.home_item_icon , item.getImageUrl().getUrl());
}
helper.setText(R.id.home_item_text , item.getTitle());
helper.setText(R.id.home_item_price , item.getPrice());
}
}
-大功告成简简单单的几行代码搞定,然后在Activity里面new HomeFuAdapter......这么简单我就不写了小伙伴们自己可以搞定的,剩下的时间可以在QQ群和一群群友们吹吹水聊聊天了!