Android BaseAdapter 封装总结(二)
上篇文章总结了关于BaseViewHolder
的封装,这篇文章总结关于模块组装Adapter的封装
多种类型的viewType,通过模块代理(Delegate)组装
首先,我们了解一下什么模块组装Adapter目的。
我们在写不同的界面的时候,往往会针对不同的界面展示,编写不同的Adapter。当某些界面具有相同元素的时候,能不能不重写Adapter,而是通过组装(add)的方式,将我们之前写好的Adapter通过AdapterDelegateManager添加(add)进来。这就是我们模块组装Adapter目的。
先打造一个AdapterDelegateManager
,来代理执行BaseAdapter中的抽象方法,主要为一下三个方法:
@Override
public int getItemViewType(int position){
return 0;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;
}
打造后的AdapterDelegateManager
如下:
/**
* @param <T> adapter 数据源
*/
public class AdapterDelegateManage<T> {
private SparseArrayCompat<AdapterDelegate<T>> delegates = new SparseArrayCompat<>();
public AdapterDelegateManage<T> addDelegate(@NonNull AdapterDelegate<T> delegate) {
int viewType = delegates.size();
if (delegates.get(viewType) != null) {
viewType++;
}
addDelegate(viewType, false, delegate);
return this;
}
public AdapterDelegateManage<T> addDelegate(int viewType, boolean allowReplacingDelegate, @NonNull AdapterDelegate<T> delegate) {
if (!allowReplacingDelegate && delegates.get(viewType) != null) {
throw new IllegalArgumentException(
"An ItemViewDelegate is already registered for the viewType = "
+ viewType
+ ". Already registered ItemViewDelegate is "
+ delegates.get(viewType));
}
delegates.put(viewType, delegate);
return this;
}
public int getItemViewType(int position, T adapterDataSource) {
int delegateCount = delegates.size();
for (int i = 0; i < delegateCount; i++) {
AdapterDelegate<T> adapterDelegate = delegates.valueAt(i);
if (adapterDelegate.isForViewType(position, adapterDataSource)) {
return delegates.keyAt(i);
}
}
throw new NullPointerException("No AdapterDelegate added that matches position=" + position + " in data source");
}
public int getAdapterDelegateCount() {
return delegates.size();
}
public AdapterDelegate<T> getDelegateByViewType(int viewType) {
return delegates.get(viewType);
}
public void convert(int position, T adapterDataSource, BaseViewHolder baseViewHolder) {
int delegateCount = delegates.size();
for (int i = 0; i < delegateCount; i++) {
AdapterDelegate<T> adapterDelegate = delegates.valueAt(i);
if (adapterDelegate.isForViewType(position, adapterDataSource)) {
adapterDelegate.convert(position,baseViewHolder, adapterDataSource);
return;
}
}
throw new NullPointerException("No AdapterDelegate added that matches position=" + position + " in data source");
}
提供一个各个模块统一的一接口AdapterDelegate<T>
,以方便AdapterDelegateManager
调用,接口如下:
/**
* Adapter 模块代理接口
*
* @param <T> adapter 数据源 i.e List<BeanName>
*/
public interface AdapterDelegate<T> {
@LayoutRes int getItemLayoutResId();
/**
* 判断
*
* @param position itemview 在Adapter中的位置
* @param adapterDataSource adapter 数据源
* @return true item 是对应viewtype,false 不是
*/
boolean isForViewType(int position, T adapterDataSource);
/**
* itemview中的子view 根据 数据,绘制界面
*
* @param position itemview 在Adapter中的位置
* @param baseViewHolder 与itemview绑定在一起的viewHolder
* @param adapterDataSource adapter 数据源
*/
void convert(int position, BaseViewHolder baseViewHolder, T adapterDataSource);
}
封装好之后,我们写两个类实现AdapterDelegate<T>
接口:
CatAdapterDelegate
public class CatAdapterDelegate implements AdapterDelegate<List<BaseModel>> {
@Override
public int getItemLayoutResId() {
return R.layout.cat_item;
}
@Override
public boolean isForViewType(int position, List<BaseModel> adapterDataSource) {
return adapterDataSource.get(position) instanceof Cat;
}
@Override
public void convert(int position, BaseViewHolder baseViewHolder, List<BaseModel> adapterDataSource) {
if (adapterDataSource.get(position) instanceof Cat) {
Cat cat = (Cat) adapterDataSource.get(position);
TextView textView = (TextView) baseViewHolder.getViewByViewId(R.id.id_tv_title);
textView.setText(cat.getName());
}
}
}
DogAdapterDelegate
public class DogAdapterDelegate implements AdapterDelegate<List<BaseModel>> {
@Override
public int getItemLayoutResId() {
return R.layout.dog_item;
}
@Override
public boolean isForViewType(int position, List<BaseModel> adapterDataSource) {
return adapterDataSource.get(position) instanceof Dog;
}
@Override
public void convert(int position, BaseViewHolder baseViewHolder, List<BaseModel> adapterDataSource) {
if (adapterDataSource.get(position) instanceof Cat) {
Dog dog = (Dog) adapterDataSource.get(position);
TextView textView = (TextView) baseViewHolder.getViewByViewId(R.id.id_tv_title);
textView.setText(dog.getName());
}
}
}
将CatAdapterDelegate
和 DogAdapterDelegate
组装到我们的Adapter中:
public class MyMultiAdapter extends BaseAdapter {
private Context context;
private List<BaseModel> baseModelList;
private AdapterDelegateManage<List<BaseModel>> adapterDelegateManage = new AdapterDelegateManage<>();
public MyMultiAdapter(Context context, List<BaseModel> baseModelList) {
this.context = context;
this.baseModelList = baseModelList;
adapterDelegateManage.addDelegate(new DogAdapterDelegate());
adapterDelegateManage.addDelegate(new CatAdapterDelegate());
}
@Override
public int getCount() {
return baseModelList.size();
}
@Override
public Object getItem(int position) {
return baseModelList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
return adapterDelegateManage.getItemViewType(position, baseModelList);
}
@Override
public int getViewTypeCount() {
return adapterDelegateManage.getAdapterDelegateCount();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
AdapterDelegate<List<BaseModel>> adapterDelegate = adapterDelegateManage.getDelegateByViewType(getItemViewType(position));
BaseViewHolder baseViewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(adapterDelegate.getItemLayoutResId(), parent, false);
baseViewHolder = new BaseViewHolder(convertView);
convertView.setTag(baseViewHolder);
} else {
baseViewHolder = (BaseViewHolder) convertView.getTag();
}
adapterDelegateManage.convert(position, baseModelList, baseViewHolder);
return convertView;
}
}
在外部调用:
public class MyListViewMultiBaseAdapterFragment extends BaseFragment {
private List<BaseModel> mDatas = new ArrayList<>();
@BindView(R.id.lv)
ListView listView;
public static MyListViewMultiBaseAdapterFragment newInstance() {
MyListViewMultiBaseAdapterFragment fragment = new MyListViewMultiBaseAdapterFragment();
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initData();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_listivew_baseadapter, container, false);
ButterKnife.bind(this, view);
initView();
return view;
}
private void initData() {
mDatas.add(new Dog("dog1"));
mDatas.add(new Dog("dog2"));
mDatas.add(new Dog("dog3"));
mDatas.add(new Cat("cat1"));
mDatas.add(new Cat("cat2"));
mDatas.add(new Cat("cat3"));
Collections.shuffle(mDatas);
}
private void initView() {
MyMultiAdapter adapter = new MyMultiAdapter(getContext(), mDatas);
listView.setAdapter(adapter);
}
}
最后我们在进一步封装我们的Adapter,将AdapterDelegateManage
的调用封装到基础的MultiCommonAdpater
中
public class MultiCommonAdpater<T extends List<?>> extends BaseAdapter {
private Context context;
private T dataList;
private AdapterDelegateManage<T> adapterDelegateManage = new AdapterDelegateManage<>();
public MultiCommonAdpater(Context context, T dataList) {
this.context = context;
this.dataList = dataList;
}
@Override
public int getCount() {
return dataList.size();
}
@Override
public Object getItem(int position) {
return dataList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
return adapterDelegateManage.getItemViewType(position, dataList);
}
@Override
public int getViewTypeCount() {
return adapterDelegateManage.getAdapterDelegateCount();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
AdapterDelegate<T> adapterDelegate = adapterDelegateManage.getDelegateByViewType(getItemViewType(position));
BaseViewHolder baseViewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(adapterDelegate.getItemLayoutResId(), parent, false);
baseViewHolder = new BaseViewHolder(convertView);
convertView.setTag(baseViewHolder);
} else {
baseViewHolder = (BaseViewHolder) convertView.getTag();
}
adapterDelegateManage.convert(position, dataList, baseViewHolder);
return convertView;
}
protected MultiCommonAdpater addItemViewDelegate(AdapterDelegate<T> adapterDelegate) {
adapterDelegateManage.addDelegate(adapterDelegate);
return this;
}
}
根据业务需要写一个Adapter时候,我们可以继承MultiCommonAdpater
,如下:
public class MyNewMultiAdapter extends MultiCommonAdpater<List<BaseModel>> {
public MyNewMultiAdapter(Context context, List<BaseModel> dataList) {
super(context, dataList);
addItemViewDelegate(new DogAdapterDelegate());
addItemViewDelegate(new CatAdapterDelegate());
}
}
是不是很简洁,一行代码就可以添加一种类型的Adapter,而且可以很方便的组装,我们还可以在AdapterDelegateManager
中封装更多的方法,比如说,removeDeleagate()
以实现删除某种item。
再来看看我们外层ListView
使用:
public class MyListViewMultiBaseAdapterFragment extends BaseFragment {
private List<BaseModel> mDatas = new ArrayList<>();
@BindView(R.id.lv)
ListView listView;
public static MyListViewMultiBaseAdapterFragment newInstance() {
MyListViewMultiBaseAdapterFragment fragment = new MyListViewMultiBaseAdapterFragment();
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initData();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_listivew_baseadapter, container, false);
ButterKnife.bind(this, view);
initView();
return view;
}
private void initData() {
mDatas.add(new Dog("dog1"));
mDatas.add(new Dog("dog2"));
mDatas.add(new Dog("dog3"));
mDatas.add(new Cat("cat1"));
mDatas.add(new Cat("cat2"));
mDatas.add(new Cat("cat3"));
Collections.shuffle(mDatas);
}
private void initView() {
// listView.setAdapter(new MultiCommonAdpater<>(getContext(), mDatas));
listView.setAdapter(new MyNewMultiAdapter(getContext(), mDatas));
}
}
好了,至此关于Adapter两种封装模式总结完成了,源码可以看下面参考资料中的两个开源库。
参考资料:
网友评论