Android高效并简约的使用ListView(二)

简介: BaseListAdapter实现public abstract class BaseListAdapter extends BaseAdapterBaseListAdapter是一个模板类继承Android SDK中的BaseAdapter,里面...

BaseListAdapter实现

public abstract class BaseListAdapter<T> extends BaseAdapter
BaseListAdapter是一个模板类继承Android SDK中的BaseAdapter,里面可以看到一个成员对象
private List<T> list = new ArrayList<>();

通过该对象装载Adater中所需要的数据,经常看到有朋友在Adapter的外部持有Adapter中list引用用来改变Adapter中的数据,其实这样会导致两个对象同时对Adapter中的数据进行改变,风险是不可控的,而且外部的list生命周期在长于Adapter的时候会导致list来不及内存回收,如果做了一些非法的操作很容易使得list对象这块内存逃逸出去,比如用一个static的引用去指向它。在Adapter中增加一些数据改变的方法可以避免这一切情况的出现,而且很方便。

/**
     * 初始化list
     *
     * @param list
     */
    public void initList(List<T> list) {
        if (this.list.size() > 0) {
            this.list.clear();
        }
        this.list.addAll(list);
        notifyDataSetChanged();
    }
    
    /**
     * add the list ,but no clear
     *
     * @param list
     */
    public void addList(List<T> list) {
        this.list.addAll(list);
        notifyDataSetChanged();
    }
    
    /**
     * clear all list
     */
    public void clearList() {
        this.list.clear();
        notifyDataSetChanged();
    }
    ```
通过这些方法使得`Adapter`才真正成为`data controller`, 在每次需要数据操作的时候对`Adapter`进行发送消息。
    下面就是真正源码抽象的过程了:
##1. 首先是getView()方法的抽象
```java
    
    @Override
    public final View getView(int position, View convertView, ViewGroup parent) {
        BaseViewHolder viewHolder = null;
        if (convertView == null) {
            viewHolder = onCreateViewHolder(position, getViewBundles());
            convertView = createView(position, viewHolder);
        } else {
            viewHolder = (BaseViewHolder) convertView.getTag();

        }
        if (convertView == null || convertView.getTag() == null)
            throw new NullPointerException(" creatview fails");
        onSetViewHolder(position, getItem(position), viewHolder);
        return convertView;
    }
    ```
在`getView`中通过`position`参数实例化对应的`viewHolder`对象`onCreateViewHolder`方法会call`getItemViewType`方法通过子类实现的`List<ViewBundle> ViewBundles`对象取得需要的ViewHolder.class类型然而通过反射去实例化。
```java  
    protected BaseViewHolder onCreateViewHolder(int pos,List<ViewBundle> ViewBundles){
        Class<? extends BaseViewHolder> clazz = ViewBundles
                .get(getItemViewType(pos)).vHClazz;
        return ViewUtil.getInstance(clazz);
    }

拿到ViewHolder对象后就可以开始进行相应的数据set了,
onSetViewHolder(position, getItem(position), viewHolder);这个是set data的方法:

/**
     * set data for viewHolder by viewType(through by getItemViewType)
     *
     * @param position
     * @param bean
     * @param baseViewHolder
     */
    protected void onSetViewHolder(int position, T bean,
                                   BaseViewHolder baseViewHolder) {
        baseViewHolder.setView(bean, getContext());

    }

在onSetViewHolder方法中可以看到回去调用ViewHolder父类的setView()方法,下面是BaseViewHolder的代码,通过baseViewHolder.setView(bean, getContext());可以调用子类的具体实现,这样就解耦了adapter和viewHolder之间的关联,并且不需要关注viewHolder的对象具体类型(因为在getViewTypeCount!=1的时候会在onBindViewHolder(List<ViewBundle> list)中绑定多个BaseViewHolder子类的类型),其实就是java多态的使用。

    public static abstract class BaseViewHolder<T> {
        public BaseViewHolder() {
        }
        protected abstract void setView(T bean, Context context);
        public Class getClassTag() {
            return this.getClass();
        }
    }

2. ViewBundle的职能?

在子类实现中有这样的一个方法onBindViewHolder(List<ViewBundle> list),ViewBundle的作用是什么呢?

    public static class ViewBundle {
        public ViewBundle(int layoutId, Class<? extends BaseViewHolder> clazz) {
            this.layoutId = layoutId;
            this.vHClazz = clazz;
        }

        public Class<? extends BaseViewHolder> vHClazz;
        public int layoutId;

        @Override
        public String toString() {
            return "ViewBundle{" + "vHClazz=" + vHClazz + ", layoutId="
                    + layoutId + '}';
        }
    }

可以看到其实是一个layoutId和viewHolder类型的对应关系,通过list将数组对象传递给父类,通过下标取得对应的class值。

到这里代码解析全部完毕,主要工作就是Adapter的简单定制,让子类的具体实现最小化。这样的处理在开发中可以减少相应的繁琐重复工作并降低错误率,父类中输出了输出了必要的log并在子类实现除错的情况跑出了对应的异常,可以很快的定位原因。
有问题请联系我:ganquan3640@gmail.com

目录
相关文章
|
6月前
|
API Android开发 开发者
Android UI设计: 什么是RecyclerView?为什么它比ListView更好?
Android UI设计: 什么是RecyclerView?为什么它比ListView更好?
85 2
|
5月前
|
API Android开发 开发者
`RecyclerView`是Android API 21引入的UI组件,用于替代ListView和GridView
【6月更文挑战第26天】`RecyclerView`是Android API 21引入的UI组件,用于替代ListView和GridView。它提供高效的数据视图复用,优化的布局管理,支持多种布局(如线性、网格),并解耦数据、适配器和视图。RecyclerView的灵活性、性能(如局部刷新和动画支持)和扩展性使其成为现代Android开发的首选,特别是在处理大规模数据集时。
65 2
|
6月前
|
XML Java Android开发
Android Studio App入门之列表视图ListView的讲解及实战(附源码 超详细必看)
Android Studio App入门之列表视图ListView的讲解及实战(附源码 超详细必看)
679 1
|
5月前
|
前端开发 API Android开发
25. 【Android教程】列表控件 ListView
25. 【Android教程】列表控件 ListView
164 2
|
6月前
|
XML Java Android开发
如何美化android程序:自定义ListView背景
如何美化android程序:自定义ListView背景
63 2
|
6月前
|
XML 编解码 Java
Android控件之高级控件——ListView、cardView、屏幕适配
Android控件之高级控件——ListView、cardView、屏幕适配
|
11月前
|
XML Android开发 数据格式
安卓-无敌解决ListView添加标题头无法正常显示的问题(歪门邪道)
安卓-无敌解决ListView添加标题头无法正常显示的问题(歪门邪道)
75 0
|
Java Android开发
[笔记]Android 学习一之转场动画+ViewPager+ListView简单Demo
[笔记]Android 学习一之转场动画+ViewPager+ListView简单Demo
|
XML Java Android开发
Android优化版ListView(附源代码)
本文是博主对Adapter(适配器)的一些理解,为了加深对Adapter的理解以及记录自己的阶段学习而写,同时也适合初学者阅读,参考本条博客的逻辑进行学习。
147 0
|
Android开发
安卓中listview点击每一条进入不同界面
安卓中listview点击每一条进入不同界面
111 0