«

高级控件AdapterView(二):通过Observer实现数据、视图同步刷新

时间:2024-3-2 19:53     作者:韩俊     分类: Android


多条目控件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类继承体系


2.1、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有关的方法


3.1、adapter中相关源码
//注册一个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有关的方法


4.1、AdapterView
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;
                }
        }   );


版权声明:本文为博主原创文章,未经博主允许不得转载。

标签: android

热门推荐