您的位置:首页 > 其它

系列笔记11、观察者模式-ListView与Adapter

2017-04-19 14:58 381 查看
Subject:抽象主题,也就是被观察者(Observable)

ConcreteSubject:具体主题

Observer:抽象观察者

ConcreteObserver:具体的观察者

观察者模式ListView与Adapter

ListView数据变化后,会调用Adapter的notifyDataSetChanged()方法,这个方法定义在BaseAdapter中

BaseAdapter.java

package android.widget;

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

    }

}

这是一个观察者模式。被观察者DataSetObservable,那么观察者是什么呢。

DataSetObservable.java

package android.database;

public class DataSetObservable extends Observable<DataSetObserver> {

    public void notifyChanged() {

        synchronized(mObservers) {

            // 调用所有观察者的onChanged方式

            //注意这里从后往前遍历,是为了防止app在onChanged()方法实现里,

            //把自己从mObservers集合里移除了,这时候正向遍历就会引起问题

            for (int i = mObservers.size() - 1; i >= 0; i--) {

                mObservers.get(i).onChanged();

            }

        }

    }

}

代码就是调用mObservers的onChanged()方法,那么这些观察者从哪里来的?其实是ListView在setAdapter()的时候设置的。

ListView.java

package android.widget;

public class ListView extends AbsListView {

    public void setAdapter(ListAdapter adapter) {

        ...

        if (mAdapter != null) {

            ...

            mDataSetObserver = new AdapterDataSetObserver();

            mAdapter.registerDataSetObserver(mDataSetObserver);

    }

}

package android.widget;

public abstract class AbsListView {

 private FastScroller mFastScroll;

 private void setFastScrollerEnabledUiThread(boolean enabled) {

        if (mFastScroll != null) {

            mFastScroll.setEnabled(enabled);

        } else if (enabled) {

            mFastScroll = new FastScroller(this, mFastScrollStyle);

            mFastScroll.setEnabled(true);

        }

        ...

    }

    /**

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

            }

        }

     }

}

package android.widget;

public abstract class AdapterView<T extends Adapter> extends ViewGroup {

  

    class AdapterDataSetObserver extends DataSetObserver {

        @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()方法刷新布局

            requestLayout();

        }

  }

  整个流程是先在ListView的setAdapter()里给被观察者DataSetObservable注册观察者AbsListView.AdapterDataSetObserver,DataSetObservable放在BaseAdapter里引用,在数据发生变化时,调用adapter的notifyDataSetChanged()方法,而该方法其实是调用了DataSetObservable的notifyChanged()方法,最终会调用observer的onChanged()方法,也就是AdapterView.AdapterDataSetObserver实现的onChanged()方法,在这个方法里会调用对应ListView的requestLayout()去刷新布局。

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: