Re:Android ListView观察者的使用

第二期项目结束,继续自己的博客生涯。上周六给自己立过一个flag,对自己的承诺一定兑现,我就是注定成为大牛的偶豆扣。

Android开发中肯定少不了ListView,它总是配合BaseAdapter一起。每次我们更新数据的时候就会调用baseAdapter.notifyDataSetChanged()方法。实际其中就是用到了观察者模式。那今天我们就来看看ListView中是如何使用观察者模式的。

让我们先看看BaseAdapter的源码,不重要的代码忽略。但是其中有个hasStableIds()方法默认返回false,后面要用到。

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    //一个被观察者实例
    private final DataSetObservable mDataSetObservable = new DataSetObservable();
    
    //注册观察者
    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
    }
    //关取观察者
    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer);
    }
    //通知所有观察者数据改变
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }

    //通知所有观察者数据更替
    public void notifyDataSetInvalidated() {
        mDataSetObservable.notifyInvalidated();
    }
BaseAdapter里有一个被观察者DataSetObservable实例,他继承自Observable,让我们来看看它们怎么写的

public abstract class Observable<T> {
    /**
     * 一个泛型T的观察者集合,
     */
    protected final ArrayList<T> mObservers = new ArrayList<T>();

    /**
     * 添加观察者到集合
     */
    public void registerObserver(T observer) {
        synchronized(mObservers) {//对象同步锁
            mObservers.add(observer);
        }
    }

    /**
     * 移除观察者
     */
    public void unregisterObserver(T observer) {
        synchronized(mObservers) {
            mObservers.remove(index);
        }
    }

    /**
     * 移除所有观察者
     */
    public void unregisterAll() {
        synchronized(mObservers) {
            mObservers.clear();
        }
    }
}

public class DataSetObservable extends Observable<DataSetObserver> {
    /**
     * 通知所有观察者数据改变
     */
    public void notifyChanged() {
        synchronized(mObservers) {//mObservers继承自Observable<T>
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }

    /**
     * 通知所有观察者数据更替
     */
    public void notifyInvalidated() {
        synchronized (mObservers) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onInvalidated();
            }
        }
    }
}
典型的被观察者的写法,其实就是用一个集合来存储观察者,然后对这个集合进行操作。

listView.setAdapter(baseAdapter);//给listview设置适配器
接下来我们看看setAdapter的方法到底干了什么

@Override
    public void setAdapter(ListAdapter adapter) {
        //对观察者模式不重要的代码省略...
        if (mAdapter != null) {
            ...
            mDataSetObserver = new AdapterDataSetObserver();
            mAdapter.registerDataSetObserver(mDataSetObserver);
	    ...
        } else {...}
        requestLayout();//重新布局
    }
还记得BaseAdapter中的registerDataSetObserver方法吗?接下来看看AdapterDataSetObserver这个观察者是怎么写的
class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
        @Override
        public void onChanged() {
            super.onChanged();
            if (mFastScroll != null) {
                mFastScroll.onSectionsChanged();
            }
        }

        @Override
        public void onInvalidated() {
            super.onInvalidated();
            if (mFastScroll != null) {
                mFastScroll.onSectionsChanged();
            }
        }
    }
AdapterDataSetObserver这个类只是单纯的设置了一下ListView的快速滚动,那我们去他的父类看看。它是AdapterView的一个内部类。

class AdapterDataSetObserver extends DataSetObserver {

        @Override
        public void onChanged() {
            mDataChanged = true;//改变状态
            mOldItemCount = mItemCount;//记录下上次的数量
            mItemCount = getAdapter().getCount();//记录下这次的数量
		//还记得hasStableIds默认返回什么吗?
            if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
                    && mOldItemCount == 0 && mItemCount > 0) {
                ....
            } else {
                rememberSyncState();//记住各种状态和数据(顶部偏移量等)
            }
            checkFocus();//检测焦点
            requestLayout();//view的方法,重新布局
        }

        @Override
        public void onInvalidated() {
            ...//重置了所有的位置状态
        }
    }
源码就看到这里,基本上逻辑已经搞清楚了。setAdapter的时候会注册一个观察者。notifyDataSetChanged的时候会通知观测者,可以让AdapterView调用相应的逻辑,最后刷新数据。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值