notifyDataSetChanged和notifyDataSetInvalidated区别以及观察者模式的使用

notifyDataSetChanged和notifyDataSetInvalidated区别以及观察者模式的使用

看Observer和Observable的时候,爬了下Listview的源码,研究了下ANdroid中用到的观察者模式


两个方法
相同点

当改变Adapter数据后,调用两个方法都会刷新视图

不同点

notifyDataSetChanged会保存刷新前的状态,比如Listview滑动的位置;
notifyDataSetInvalidated会清空所有信息,重新布局,位置会到最上方;

源码

源码位于AdapterView中的内部类AdapterDataSetObserver (观察者)

class AdapterDataSetObserver extends DataSetObserver {

        private Parcelable mInstanceState = null;

        @Override
        public void onChanged() {
            mDataChanged = true;
            mOldItemCount = mItemCount;
            mItemCount = getAdapter().getCount();

            // Detect the case where a cursor that was previously invalidated has
            // been repopulated with new data.
            if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
                    && mOldItemCount == 0 && mItemCount > 0) {
                AdapterView.this.onRestoreInstanceState(mInstanceState);
                mInstanceState = null;
            } else {
                rememberSyncState();
            }
            checkFocus();
            requestLayout();
        }

        @Override
        public void onInvalidated() {
            mDataChanged = true;

            if (AdapterView.this.getAdapter().hasStableIds()) {
                // Remember the current state for the case where our hosting activity is being
                // stopped and later restarted
                mInstanceState = AdapterView.this.onSaveInstanceState();
            }

            // Data is invalid so we should reset our state
            mOldItemCount = mItemCount;
            mItemCount = 0;
            mSelectedPosition = INVALID_POSITION;
            mSelectedRowId = INVALID_ROW_ID;
            mNextSelectedPosition = INVALID_POSITION;
            mNextSelectedRowId = INVALID_ROW_ID;
            mNeedSync = false;

            checkFocus();
            requestLayout();
        }

        public void clearSavedState() {
            mInstanceState = null;
        }
    }
源码说明
  • notifyDataSetChanged

    当调用notifyDataSetChanged,通过观察中会调用到onChanged,
    其中AdapterView.this.onRestoreInstanceState(mInstanceState);保存了当前Listview布局信息;
    最终调用父类 View 中`requestLayout()`重新布局;

  • 当调用notifyDataSetInvalidated , onInvalidated会被调用,布局信息被初始化,最终调用requestLayout,布局恢复初始状态。

使用场景

如果需要adapter丢弃用户操作后的信息,可以调用notifyDataSetInvalidated ,让listview初始化;反之则调用notifyDataSetChanged,让当前页面的位置,选中状态等信息保持不变;
当然最终使用场景可以分别调用两种方法实验。


观察者模式在Listview中的使用

Android 没有使用java提供的Observable ,而是使用Android源码中android.database.Observable<>

观察者模式的具体实现
  • 基类 Observable中 registerObserver unregisterObserver提供添加和删除观察者的方法;
  • 子类 DataSetObservable继承Observable,提供notifyChanged 通知mObserver.onChanged(),提供notifyInvalidated调用 mObserver.onInvalidated;
  • 观察者 DataSetObserver 中提供了 onChanged和onInvalidated两个未实现的方法;
  • Listview系列view的基类adapterView中提供了内部类AdapterDataSetObserver 继承DataSetObserver 实现了DataSetObserver的两个方法,用了操作ListView不同的状态;
具体实现
  • BaseAdapter中注册mDataSetObservable 被观察者,以及通知观察者
    DataSetObservable mDataSetObservable = new DataSetObservable();
    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
    }
    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer);
    }
    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer);
    }
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }
  • AbsListView中注册和解绑
    @Override
    protected void onAttachedToWindow() {
        mDataSetObserver = new AdapterDataSetObserver();
        mAdapter.registerDataSetObserver(mDataSetObserver);
    }
     @Override
    protected void onDetachedFromWindow() {
        mAdapter.unregisterDataSetObserver(mDataSetObserver);
        mDataSetObserver = null;
    }
  • 在加上文章最上面的源码,一套流程over

源码爬的很开心,pompip原创

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值