reference
Android listview base class package, single entry package for universal adapter (advanced article)
CommonHolder
public class CommonHolder {
/**
* 控件ID
*/
private SparseArray<View> views;
/**
* 视图
*/
private View convertView;
private CommonHolder(Context context, ViewGroup parent, int layoutId) {
views = new SparseArray<>();
convertView = LayoutInflater.from(context).inflate(layoutId, parent, false);
convertView.setTag(this);
}
public static CommonHolder get(Context context, View convertView,
ViewGroup parent, int layoutId) {
if (null == convertView) {
return new CommonHolder(context, parent, layoutId);
} else {
return (CommonHolder) convertView.getTag();
}
}
/**
* 获得控件
* @param viewId 控件id
* @param <T> 控件泛型
* @return 控件
*/
public <T extends View> T getView(int viewId) {
View view = views.get(viewId);
if (null == view) {
view = convertView.findViewById(viewId);
views.put(viewId, view);
}
return (T) view;
}
/**
* 获得视图
* @return 视图
*/
public View getConvertView() {
return convertView;
}
/**
* 对文本控件赋值
* @param viewId 控件ID
* @param text 内容
*/
public void setText(int viewId, String text) {
TextView view = getView(viewId);
view.setText(text);
}
/**
* 设置控件的监听事件
* @param viewId 控件ID
* @param listener 监听器
*/
public void setOnClickListener(int viewId, View.OnClickListener listener) {
View view = getView(viewId);
view.setOnClickListener(listener);
}
}
ItemViewDelegate
public interface ItemViewDelegate<T> {
/**
* 设置多条目布局
* @return 布局ID
*/
int getItemViewLayoutId();
/**
* 判断是否使用当前布局
* @param item 泛型数据
* @param position 下标
* @return 是否使用当前布局
*/
boolean isForViewType(T item, int position);
/**
* 数据处理
* @param holder 控件持有类
* @param t 泛型数据
* @param position 下标
*/
void convert(CommonHolder holder, T t, int position);
}
ItemViewDelegateManager
public class ItemViewDelegateManager<T> {
/**
* 多条目布局
*/
private SparseArray<ItemViewDelegate<T>> delegates;
ItemViewDelegateManager() {
delegates = new SparseArray<>();
}
/**
* 添加布局
* viewType :以数组长度为布局类型和key值,可以保证key值不重复
*
* @param delegate 布局
*/
public void addDelegate(ItemViewDelegate<T> delegate) {
if (null != delegate) {
int viewType = delegates.size();
delegates.put(viewType, delegate);
}
}
/**
* 添加布局
*
* @param delegate 布局
* @param viewType 类型
*/
public void addDelegate(ItemViewDelegate<T> delegate, int viewType) {
if (null != delegate && null != delegates.get(viewType)) {
delegates.put(viewType, delegate);
}
}
/**
* 根据布局删除指定布局
*
* @param delegate 布局
*/
public void removeDelegate(ItemViewDelegate<T> delegate) {
if (null != delegate) {
int indexToRemove = delegates.indexOfValue(delegate);
if (0 <= indexToRemove) {
delegates.removeAt(indexToRemove);
}
}
}
/**
* 根据布局类型删除指定布局
*
* @param viewType 布局类型
*/
public void removeDelegate(int viewType) {
int indexToRemove = delegates.indexOfKey(viewType);
if (0 <= indexToRemove) {
delegates.removeAt(indexToRemove);
}
}
/**
* 判断是否存在多条目布局
* @return 是否存在
*/
public boolean isHaveDelegate() {
return getItemViewDelegateCount() > 0;
}
/**
* 获取多条目布局数量
*
* @return 布局数量
*/
public int getItemViewDelegateCount() {
return delegates.size();
}
/**
* 获取布局类型
*
* @param item 数据
* @param position 下标
* @return 布局类型
*/
public int getItemViewType(T item, int position) {
int delegatesCount = delegates.size();
for (int i = 0; i < delegatesCount; i++) {
ItemViewDelegate<T> delegate = delegates.valueAt(i);
if (delegate.isForViewType(item, position)) {
return delegates.keyAt(i);
}
}
throw new IllegalArgumentException("");
}
/**
* 返回当前的布局
*
* @param item 泛型数据
* @param position 下标
* @return 布局
*/
public ItemViewDelegate getItemViewDelegate(T item, int position) {
int delegatesCount = delegates.size();
for (int i = delegatesCount - 1; i >= 0; i--) {
ItemViewDelegate<T> delegate = delegates.valueAt(i);
if (delegate.isForViewType(item, position)) {
return delegate;
}
}
throw new IllegalArgumentException("delegates is not");
}
/**
* 处理数据
* @param holder 控件持有类
* @param item 泛型数据
* @param position 下标
*/
public void convert(CommonHolder holder, T item, int position) {
int delegatesCount = delegates.size();
for (int i = 0; i < delegatesCount; i++) {
ItemViewDelegate<T> delegate = delegates.valueAt(i);
if (delegate.isForViewType(item, position)) {
delegate.convert(holder,item,position);
return;
}
}
throw new IllegalArgumentException("delegates is hot");
}
}
MultiItemTypeAdapter
public class MultiItemTypeAdapter<T> extends BaseAdapter {
/**
* 上下文
*/
private Context context;
/**
* 泛型数据
*/
private List<T> data;
/**
* 多条目布局管理
*/
private final ItemViewDelegateManager<T> manager;
public MultiItemTypeAdapter(Context context,List<T> data) {
this.context = context;
this.data=data;
manager = new ItemViewDelegateManager<>();
}
/**
* 添加布局
* @param itemViewDelegate 布局
*/
public void addItemViewDelegate(ItemViewDelegate<T> itemViewDelegate){
manager.addDelegate(itemViewDelegate);
}
@Override
public int getCount() {
return data.size();
}
@Override
public T getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getViewTypeCount() {
if (manager.isHaveDelegate()){
return manager.getItemViewDelegateCount();
}
return super.getViewTypeCount();
}
@Override
public int getItemViewType(int position) {
if (manager.isHaveDelegate()){
return manager.getItemViewType(data.get(position),position);
}
return super.getItemViewType(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ItemViewDelegate itemViewDelegate = manager.getItemViewDelegate(data.get(position), position);
CommonHolder holder = getViewHolder(convertView, parent, itemViewDelegate.getItemViewLayoutId());
convert(holder,getItem(position),position);
return holder.getConvertView();
}
/**
* 处理数据
* @param holder 控件持有类
* @param data 数据
*/
public void convert(CommonHolder holder, T data,int position){
manager.convert(holder,data,position);
}
private CommonHolder getViewHolder(View convertView, ViewGroup parent,int itemLayoutId){
return CommonHolder.get(context, convertView, parent, itemLayoutId);
}
}
CommonAdapter
public abstract class CommonAdapter<T> extends MultiItemTypeAdapter<T> {
public CommonAdapter(Context context, final List<T> data, final int layoutId) {
super(context, data);
addItemViewDelegate(new ItemViewDelegate<T>() {
@Override
public int getItemViewLayoutId() {
return layoutId;
}
@Override
public boolean isForViewType(T item, int position) {
return true;
}
@Override
public void convert(CommonHolder holder, T t, int position) {
CommonAdapter.this.convert(holder,t,position);
}
});
}
/**
* 数据控制
* @param holder 控件持有类
* @param data 数据
* @param position 下标
*/
@Override
public abstract void convert(CommonHolder holder, T data,int position);
}
Basic single entry usage
listView.setAdapter(new CommonAdapter<String>(this,lists,R.layout.text_item) {
@Override
public void convert(CommonHolder holder, String data, int position) {
holder.setText(R.id.text,data);
}
});
Multi-entry use
MultiItemTypeAdapter<TestDemo> adapter = new MultiItemTypeAdapter<>(this, lists);
adapter.addItemViewDelegate(new Text());
adapter.addItemViewDelegate(new Img());
listView.setAdapter(adapter);
public class Text implements ItemViewDelegate<TestDemo> {
@Override
public int getItemViewLayoutId() {
return R.layout.text_item;
}
@Override
public boolean isForViewType(TestDemo item, int position) {
return item.getType()==0;
}
@Override
public void convert(CommonHolder holder, TestDemo testDemo, int position) {
holder.setText(R.id.text,testDemo.getText());
}
}
public class Img implements ItemViewDelegate<TestDemo> {
@Override
public int getItemViewLayoutId() {
return R.layout.img_item;
}
@Override
public boolean isForViewType(TestDemo item, int position) {
return item.getType()==1;
}
@Override
public void convert(CommonHolder holder, TestDemo testDemo, int position) {
}
}