说明
我们都见过各种adapter
了,虽然说开发规范里写着DRY
,但是学习一下基础知识还是不错的
而且在开发手上的一个项目时发现github
上的一些adapter
都不够符合业务需求,所以索性自己开发了一个通用adapter
什么是adapter
我认为adapter
就是listview
、gridview
等列表的管理者,它负责提供数据和视图
ButterKnife的好处
经常看见各种adapter
里都写了findViewByID
的辅助方法,方便对item
进行视图绑定,我推荐使用ButterKnife
进行这个操作,没有必要单独写个方法
而且是自己的项目,确定已经引入了ButterKnife
包。所以这个adpter
的使用前提是项目引入了ButterKnife
包。
ViewHolder的使用
接着说视图绑定,为了使代码更简洁有序,我使用了ButterKnife
和ViewHolder
,简单来说ViewHolder
维护了一些视图的引用,方便adpter
对视图进行
个性化操作,如设置文本内容、颜色或其他属性。以下为CommonViewHolder
的关键代码
/**
* Created by zongren on 16/5/4.
*/
public abstract class CommonViewHolder {
private View mView;
public CommonViewHolder() {
}
public CommonViewHolder(View view) {
setView(view);
}
public View getView() {
return mView;
}
public void setView(View view) {
mView = view;
ButterKnife.bind(this, view);
}
}
首先这个类是虚类,使用的时候需要继承它然后生成实例,我觉得必须这么设定,因为不同的ViewHolder
肯定是绑定了不同的视图,没有必要做为实类
以下为使用例子
/**
* Created by zongren on 16/5/13.
*/
public class CategoryViewHolder extends CommonViewHolder {
@Bind(R.id.item_category_thumb_imageView)
public ImageView thumbImageView;
@Bind(R.id.item_category_title_textView)
public TextView titleTextView;
}
我直接把thumbImageView
和titleTextView
的属性设置为public
,方便adapter
对视图操作,也可以写单独的setter方法对它们进行操作
Model的使用
通常情况下,listView
的item
都是比较丰富的,不只是简单的一个textView
,那么就需要定义Model
,方便管理数据。以下为CategoryModel
的关键代码
/**
* Created by zongren on 16/4/21.
*/
public class CategoryModel {
private String mTitle;
private String mCategoryId;
private String mImageUrl;
public CategoryModel(String title, String categoryId) {
mTitle = title;
mCategoryId = categoryId;
}
public String getTitle() {
return mTitle;
}
public void setTitle(String title) {
this.mTitle = mTitle;
}
public String getCategoryId() {
return mCategoryId;
}
public void setCategoryId(String categoryId) {
this.mCategoryId = mCategoryId;
}
public String getImageUrl() {
return mImageUrl;
}
public void setImageUrl(String imageUrl) {
this.mImageUrl = mImageUrl;
}
@Override
public String toString() {
return mTitle;
}
}
Adapter的写法
以上介绍了Adapter
用到的若干个元素,现在说一下本体的写法,关键代码如下:
/**
* Created by zongren on 16/5/4.
*/
public abstract class CommonAdapter<T, V extends CommonViewHolder> extends BaseAdapter {
private static final String TAG = "CommonAdapter";
protected List<T> mData;
protected int mItemLayoutId;
private Context mContext;
public CommonAdapter(Context context, int itemLayoutId, List<T> data) {
super();
mContext = context;
mItemLayoutId = itemLayoutId;
mData = data;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public View getView(int position, View convertView, ViewGroup container) {
if (convertView == null) {
convertView = inflateView(position, container, false);
V viewHolder = getViewHolder();
viewHolder.setView(convertView);
convertView.setTag(viewHolder);
}
V viewHolder = (V) convertView.getTag();
convertView(viewHolder, mData.get(position));
return convertView;
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
public long getItemId(int position) {
return position;
}
protected View inflateView(int position, ViewGroup container, boolean attach) {
return LayoutInflater.from(mContext).inflate(mItemLayoutId, container, attach);
}
public abstract V getViewHolder();
public abstract void convertView(V viewHolder, T data);
public List<T> getData() {
return mData;
}
public void setData(List<T> data) {
mData = data;
}
}
可以看到,我同样把adapter
设置成了虚类,原因和ViewHolder
设置为虚类一样,不再赘述。T
表示Model
的类型,V
表示ViewHolder
的类型,这两个要在声明adapter
的使用提供protected View inflateView(ViewGroup container, boolean attach)
方法是用来渲染每个item
的视图的,如果item
的样式是不固定的,可以在实体类中重写这个方法,例如
@Override
protected View inflateView(int position, ViewGroup container, boolean attach) {
return LayoutInflater.from(mContext).inflate(mLayouts.get(position), container, attach);
}
public abstract V getViewHolder()
是一个需要实现的方法,用来提供V类型的ViewHolderpublic abstract void convertView(V viewHolder, T data);
是另外一个需要实现的方法,用来对viewHolder中的视图进行个性化更改
以下为CommonAdapter
的具体使用,T
为CategoryModel
,V
为CategoryViewHolder
new CommonAdapter<CategoryModel, CategoryViewHolder>(getContext(), R.layout.item_category, mLevelTwoCategories) {
@Override
public CategoryViewHolder getViewHolder() {
return new CategoryViewHolder();
}
@Override
public void convertView(CategoryViewHolder viewHolder, CategoryModel data) {
viewHolder.titleTextView.setText(data.getTitle());
}
};