ListView原理及设计模式浅析

图1

1.简介

ListView是Android使用频率非常高的一个控件,它以列表的形式展示内容,并且能够根据数据的长度自适应高度。

2.展示列表所需要的元素组成

1.需要用来展示列表的ListView
2.用来组织数据并映射到ListViewAdapter
3.需要展示的数据集
4.需要展示的View模板

3.各组成之间的关系

ListView只负责加载、管理视图,至于有多少数据,每一项数据要怎么来展示,这些它都不关心。
Adapter使用Adapter模式,使用抽象方式将用户需要指定的数据抽象出来,让用户去实现。比如:有多少数据需要展示、用什么方式来进行展示等等。
需要实现的Adapter的函数为:

1.getCount():指定当前有多少数据需要展示
2.getItem(int):获取当前position位置的数据
3.getItemId(int):直接返回当前对应的position
4.getView(int,View,ViewGroup):返回当前position对应的itemview

4.ListView原理

当处理较大的数据时,Listview并不是一次性加载所有数据,而是只加载铺满整个屏幕的数据。当屏幕向下滚动时,第一个元素离开了屏幕之后会进入到Listview里的一个Recycler集合中,Recycler会将当前视图缓存。这时最下面需要填充一个新的元素,ListView会先去Recycler集合里去取,如果有就会复用此视图,如果没有就接着创建。通过getView(int,View,ViewGroup)方法将所取到的数据传递给用户来进行复用,如果没有传递的convertView将为null.

上面这张图很好的说明了ListView的复用原理。

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View mView = null;
    if (convertView != null)
        mView = convertView;
    else {
        //重新加载视图
        mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, null);
    }
    //这里将数据和视图进行绑定

    return mView;
}

这里的position表示当前item是第几项数据,convertView表示缓存的item viewparent表示item view的父视图,这里所指的就是我们的Listview。这里最重要的就是convertView,如果convertView不为空,可以直接复用该视图,如果为空,就要重新创建视图,最后返回当前item所对应的已绑定数据的view.

5.ListView设计模式解析

listView运用了Adapter模式,而在Adapter类中却还运用了观察者模式,Adapter内部有一个被观察者类,ListView作为它的一个观察者,在将Adapter设置给ListView时,ListView就被当作观察者注册到了Adapter内的被观察者对象上了。
我们以ListView的数据刷新来通过源码实现来看看其设计模式

@Override
public void setAdapter(ListAdapter adapter) {
    //代码省略...
    super.setAdapter(adapter);
        //代码省略...
    mDataSetObserver = new AdapterDataSetObserver();
    mAdapter.registerDataSetObserver(mDataSetObserver);
        //代码省略...
}

上面源码说明在setAdapter方法里创建了一个AdapterDataSetObserver对象,并把该对象注册到了mAdapter

再来看看我们Adapter的父类BaseAdapter

BaseAdapter基类中我们看到了上面的AdapterDataSetObserver类被注册到了DataSetObservable被观察者对象中。

接下来我们来看看DataSetObservable

从图上可以看出DataSetObservable就是继承了Java提供的被观察者对象,并通过notifyChanged来通知注册了的观察者对象。

到这里还是没有看到ListView注册了Adapter。而注册的是AdapterDataSetObserver对象。那我们就去看看这个AdapterDataSetObservable这个对象的实现吧。


从图上可以看出,这是一个典型的Observer的实现,通过实现onChanged来接收被观察都传递过来的数据。在onChanged方法里调用了父类的方法,我们去父类一探究竟。


AdapterDataSetObserveronChanged方法中,我们获取了item的个数,以及调用requestLayout方法来进行重新布局,绘制整个listViewitem View.执行完此过程后,ListView中的数据就得到了刷新。

这里的AdapterDataSetObserver对象里调用的都是AdapterView或者ViewGroup类的属性或方法完成功能.而ListView继承自AdapterView.因此,只可以说AdapterDataSetObserver只是在外层做了一下包装,核心的功能应该是ListView,确切的说是AdapterViewListView通过Adapter模式、观察者模式、以及使用item View复用来高效的展示列表数据