观察者模式----以ListView和Rxjava为例

1.首先什么是观察者模式?

通过现实中的一个例子说明:

杂志社(被观察者)———-读者(观察者)

读者通过订阅杂志社的期刊,杂志社每当有新的期刊发布都会邮寄给读者,读者便可以了解期刊的内容。杂志社有一份名单(即List集合),名单的成员是通过注册的方式添加的。新杂志一出来,杂志社就遍历名单,给每一个注册的读者邮寄一本杂志,而不需要读者经常关注杂志是否更新,节省了读者的精力,即节约了资源。

其实观察者模式就是这么简单的一个道理。

2.ListView中的应用

最常用的ListView如果数据源改变,经常会调用notifyDataSetChanged方法,先看源码。

    public void notifyDataSetChanged() {
    //看到observable就应该知道跟观察者模式沾边了,
        mDataSetObservable.notifyChanged();
    }

再看notifyChanged方法源码:mObservers是一个List观察者集合。即通过notifyDataSetChanged方法最终调用的观察者集合中每个观察者的onChaged方法。

public void notifyChanged() {
        synchronized(mObservers) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }

看到这里好像差不多已经知道ListView刷新界面机制就是通过观察者模式,但是又没有十足的把握,不急,我们再看一下BaseAdapter源码

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    //注意此处构建了一个被观察者
    private final DataSetObservable mDataSetObservable = new DataSetObservable();

    public boolean hasStableIds() {
        return false;
    }
    //注册观察者
    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
    }
    //解除绑定观察者
    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer);
    }

有吃完全可以断定,就是应用的观察者模式。但是在每个观察者onchange方法里到底干了什么,我们还是不清楚。
接下来 看一下setAdapter的源码。

 @Override
    public void setAdapter(ListAdapter adapter) {

        if (mAdapter != null && mDataSetObserver != null) {
        //从这里就可以看出来当setAdatpter的时候,首先做了一个解绑的动作,惯例操作
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
        }

        resetList();
        mRecycler.clear();

        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
            mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
        } else {
            mAdapter = adapter;
        }

        mOldSelectedPosition = INVALID_POSITION;
        mOldSelectedRowId = INVALID_ROW_ID;

        // AbsListView#setAdapter will update choice mode states.
        super.setAdapter(adapter);

        if (mAdapter != null) {
            mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
            mOldItemCount = mItemCount;
            mItemCount = mAdapter.getCount();
            checkFocus();
        //创建了一个观察者,查看AdapterDataSetObserver的源码
            mDataSetObserver = new AdapterDataSetObserver();
            //并且注册到被观察者中。
            mAdapter.registerDataSetObserver(mDataSetObserver);

            mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());

            int position;
            if (mStackFromBottom) {
                position = lookForSelectablePosition(mItemCount - 1, false);
            } else {
                position = lookForSelectablePosition(0, true);
            }
            setSelectedPositionInt(position);
            setNextSelectedPositionInt(position);

            if (mItemCount == 0) {
                // Nothing selected
                checkSelectionChanged();
            }
        } else {
            mAreAllItemsSelectable = true;
            checkFocus();
            // Nothing selected
            checkSelectionChanged();
        }

        requestLayout();
    }

查看AdapterDataSetObserver的源码:是在ListView的父类AbsListView中定义的

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();
            }
        }
    }

这里调用的onChange方法里面,是在也看不出个所以然,是super.onchage();再找到它的父类AdapterView.AdapterDataSetObserver

class AdapterDataSetObserver extends DataSetObserver {

        private Parcelable mInstanceState = null;

        @Override
        public void onChanged() {
            //获取新的数目
            mDataChanged = true;
            mOldItemCount = mItemCount;
            mItemCount = getAdapter().getCount();


            if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
                    && mOldItemCount == 0 && mItemCount > 0) {
                AdapterView.this.onRestoreInstanceState(mInstanceState);
                mInstanceState = null;
            } else {
                rememberSyncState();
            }
            checkFocus();
            //重新布局,往下重新布局不在看。
            requestLayout();
        }
//省略
}

到此终于告一段落,找到了元凶,实现就在AdapterDataSetObserver中的onchange方法里,获取新的list数目,重新布局,从而实现刷新界面。

3.RxJava

RxJava是典型的观察者模式。
1.RxJava中的被观察者是Observable,观察者是Observer和Subscriber,Observer最终也会先成为Subscriber。
2.订阅关系,是被观察者把观察者放进名单

observable.subscribe(observer);
// 或者:
observable.subscribe(subscriber);

3.达成契约关系,Observable会依次发送队列中消息,调用观察者的一系列方法,如onNext,最后一个调用onComplete,发生错误则会调用onError,后两个方法还是互斥,只能调用一个。
4.同时,被观察者与观察者也是有注册,解除注册,判断是否注册等一系列方法来改变二者之间的契约关系。
5.不多介绍,是典型的观察者模式。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值