多条目控件AdapterView是仿MVC设计模式进行设计的,即AdapterView与数据是分离的,AdapterView并不直接操作数据,而是利用中间件适配器Adapter,实际上,完整的AdapterView显示是三个逻辑部分:AdapterView+Adapter+Data,Adapter相当于MVC中的控制器C,AdapterView相当于MVC中的视图V,顺便说一句,Android程序设计,也是利用MVC控制模式。既然视图与数据是分离的,那么当数据有更新时,视图显然无法自动更新,Adapter必须实时监控数据变化并刷新视图,这里用到的是Observer(观察者模式)。
一、DataSetObserver类
DataSetObserver类的API这样描述:DataSetObserver(观察者)通常设置给Cursor或Adapter,如果数据发生变化则回调该类方法。DataSetObserver类无法单独调用,必须配合DataSetObservable类使用。该类的实例即是Observer,观察者的刷新视图行为是由onChanged以及onInvalidated方法决定的,通常在AdapterView控件,如ListView中继承该类,并通过重写这两个方法,实现针对性的视图刷新。
public abstract class DataSetObserver {
//当被观察的数据发生变化,回调该函数 public void onChanged() //当被观察的数据失效,回调该函数 public void onInvalidated()
二、Observable类继承体系
这是一个抽象基类,该类主要提供对Observer进行注册或解除注册到ArrayList数据集(Observer必须绑定到某个数据集才能监测)。 源码如下:
public abstract class Observable<T> { //观察者列表,不可重复 protected final ArrayList<T> mObservers = new ArrayList<T>(); //注册观察者observer,即将observer添加到mObservers中 public void registerObserver(T observer) { //解除观察者observer,即将observer从mObservers中移除 public void unregisterObserver(T observer) { //解除所有的observer,即清空mObservers列表 public void unregisterAll() { }
2.2、DataSetObservable类
这是一个可实例化类,通常在对ArrayList数据进行更新后,主动调用notifyChanged()函数,若ArrayList数据失效,比如给视图绑定新的数据源等等,调用notifyInvalidated,源码如下:
public class DataSetObservable extends Observable<DataSetObserver> { //当数据集发生变化,回调数据集每一个观察者DataSetObserver的onChanged函数,通常视图的刷新在onChanged中完成 public void notifyChanged() { synchronized(mObservers) { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onChanged(); } } } //当数据集失效(比如关闭),回调数据集每一个观察者DataSetObserver的onInvalidated()函数 public void notifyInvalidated() { synchronized (mObservers) { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onInvalidated(); } } } }
三、适配器Adapter中与DataSetObserver有关的方法
//注册一个observer,观察Adapter关联的数据集是否发生变化(如增加、删除等等) void registerDataSetObserver(DataSetObserver observer); //取消注册observer void unregisterDataSetObserver(DataSetObserver observer);
3.2、BaseAdapter中相关源码
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { //获取DataSetObservable()对象 private final DataSetObservable mDataSetObservable = new DataSetObservable(); //注册一个DataSetObserver public void registerDataSetObserver(DataSetObserver observer) { mDataSetObservable.registerObserver(observer); } //取消一个DataSetObserver public void unregisterDataSetObserver(DataSetObserver observer) { mDataSetObservable.unregisterObserver(observer); } //通知观察数据集的observers,数据已经发生变化,并且执行与数据相关的视图刷新操作 public void notifyDataSetChanged() { mDataSetObservable.notifyChanged(); } //通知观察数据集的observers,数据已经失效,一旦调用该函数,表明Adapter也已经失效。 public void notifyDataSetInvalidated() { mDataSetObservable.notifyInvalidated(); }
3.3、小结 Adapter主要是注册一个Observer,然后在数据有变化时,主动调用notifyDataSetChanged()或notifyInvalidated(),而决定数据在出现变化后的行为(主要是onchanged()方法决定),一般需要在AdapterView中进行个性定制。
四、AdapterView中与DataSetObserver有关的方法
AdapterView中写了一个继承DataSetObserver的内部类AdapterDataSetObserver,主要是重新onChanged(),onInvalidated()方法,以执行AdapterView的刷新视图操作
class AdapterDataSetObserver extends DataSetObserver { @Override public void onChanged() { ... } @Override public void onInvalidated() { ... } }
4.2、ListView
ListView中,主要是setAdapter()方法将适配器Adapter绑定到ListView,并设置Adapter的观察者为AdapterDataSetObserver。
public void setAdapter(ListAdapter adapter) { mAdapter = adapter; if (mAdapter != null) { //注册Adapter的观察者AdapterDataSetObserver mDataSetObserver = new AdapterDataSetObserver(); mAdapter.registerDataSetObserver(mDataSetObserver); mRecycler.setViewTypeCount(mAdapter.getViewTypeCount()); }
4.3、小结
AdapterView控件主要定义Observer行为,即Onchanged()和onInvalidated()方法,然后通过Adapter的注册方法registerDataSetObserver()对定制的mDataSetObserver注册。
五、简单Demo
实现长按长按ListView并删除所在项,主要代码如下:
listview.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { //长按删除并动态更新listview datas.remove(position); myAdapter.notifyDataSetChanged(); return false; } } );
版权声明:本文为博主原创文章,未经博主允许不得转载。