ListView所用到的观察者模式浅析

前言:在我们使用listview的时候,例如使用网络请求返回一个数据显示在listview上,对listview里的子控件赋值后,我们都会调用adapter.notifyDataSetChanged()方法来刷新listview,界面就显示了那个数据,其中的原理是通过观察者模式来实现的。这里以BaseAdapter为例

BaseAdapter源码

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 里面定义了一个具体被观察者mDataSetObservable ,还有四个方法(注重前三个):注册观察者,删除观察者,通知观察者干活

listview.setAdapter源码

public class ListView extends AbsListView {
    .................
    public void setAdapter(ListAdapter adapter) {
        if (mAdapter != null && mDataSetObserver != null) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
        }
        ............
        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
            mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, adapter);
        } else {
            mAdapter = adapter;//!!!
        }

        super.setAdapter(adapter);

        if (mAdapter != null) {
            ............
            mDataSetObserver = new AdapterDataSetObserver();//!!!
            mAdapter.registerDataSetObserver(mDataSetObserver);//!!!
            ............
        } 
    }
    .................
}

说明:刚开始会先判断是否已经有别的adapter和listview绑定了,有就注销之前的具体观察者(免得待会要通知它)
注意看我标注的//!!!那三行代码:

  • 把adapter参数赋给成员变量mAdapter;
  • 定义一个AdapterDataSetObserver对象
  • 调用mAdapter(实际上这里是BaseAdapter对象)注册方法注册AdapterDataSetObserver对象(干活那个)
    不难理解AdapterDataSetObserver肯定是继承了抽象观察者类的

    下面看AdapterDataSetObserver源码:

AdapterDataSetObserver 定义在抽象类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();
            }
        }
    }

调用onChanged方法里面会调用父类super.onChanged()方法,如下:

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

说明:是不是很清楚了,它继承了抽象观察者类,重写onChanged()方法,里面逻辑就是把listview的界面重新布局,让数据重新显示。

总结

  • BaseAdapter里面有一个具体被观察者
  • listview.setAdapter(BaseAdapter对象)里面生成一个具体观察者,调用BaseAdapter对象注册具体观察者
  • 调用adapter.notifyDataSetChanged()方法后,adapter就是BaseAdapter对象,所以会调用BaseAdapter里面的具体被观察者mDataSetObservable的notifyChanged()方法(通知列表的所有观察者干活)
  • 调用AdapterDataSetObserver的onChanged()方法,显示数据

观察者模式让数据和界面都依赖于借口,实现了解耦,方便扩展工作。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值