美文网首页
Android BaseAdapter 封装总结(二)

Android BaseAdapter 封装总结(二)

作者: littlezan | 来源:发表于2017-03-03 17:12 被阅读192次

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());
        }
    }
}

CatAdapterDelegateDogAdapterDelegate 组装到我们的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两种封装模式总结完成了,源码可以看下面参考资料中的两个开源库。

参考资料:

相关文章

网友评论

      本文标题:Android BaseAdapter 封装总结(二)

      本文链接:https://www.haomeiwen.com/subject/swergttx.html