首页 > 代码库 > Android源码与设计模式之notifyDataSetChanged()方法与观察者模式

Android源码与设计模式之notifyDataSetChanged()方法与观察者模式

BaseAdapter在调用notifyDataSetChanged()方法后,GridView就刷新了,下面从源码角度对此原理进行剖析。

首先进到BaseAdapter中查看其notifyDataSetChanged()方法,发现它调用了DataSetObservable的notifyChanged()方法

public abstract class BaseAdapter{
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的notifyChanged()方法,发现它调用了mObservers.get(i)的onChanged()方法,即DataSetObserver的onChanged()方法。

public class DataSetObservable extends Observable<DataSetObserver> {
...
    public void notifyChanged() {
        synchronized(mObservers) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }
... }

其中的mObservers是在这里赋值的。

public abstract class Observable<T> {
   
    protected final ArrayList<T> mObservers = new ArrayList<T>();
     
    public void registerObserver(T observer) {
        if (observer == null) {
            throw new IllegalArgumentException("The observer is null.");
        }
        synchronized(mObservers) {
            if (mObservers.contains(observer)) {
                throw new IllegalStateException("Observer " + observer + " is already registered.");
            }
            mObservers.add(observer);
        }
    }
}

接下来寻找registerObserver()方法是在哪里调用的,发现刚才的BaseAdapter的registerDataSetObserver()方法调用了它。

而此方法是在GridView的setAdapter方法中被调用的。

...class GridView ...{
...
@Override
    public void setAdapter(ListAdapter adapter) {
        ...

        resetList();
        mRecycler.clear();        
        mAdapter = adapter;

    ...
if (mAdapter != null) { ... mDataSetObserver = new AdapterDataSetObserver(); mAdapter.registerDataSetObserver(mDataSetObserver); ... } else { checkFocus(); // Nothing selected checkSelectionChanged(); } requestLayout(); } ... }

传进去的是AdapterDataSetObserver这个类,具体的刷新动作就是在这个类的onChanged()方法中完成的。

class AdapterDataSetObserver extends DataSetObserver
 2   {
 3     private Parcelable mInstanceState = null;
 4 
 5     AdapterDataSetObserver() {
 6     }
 7     public void onChanged() { mDataChanged = true;
 8       mOldItemCount = mItemCount;
 9       mItemCount = getAdapter().getCount();
10 
11       if ((getAdapter().hasStableIds()) && (mInstanceState != null) && (mOldItemCount == 0) && (mItemCount > 0))
12       {
13         onRestoreInstanceState(mInstanceState);
14         mInstanceState = null;
15       } else {
16         rememberSyncState();
17       }
18       checkFocus();
19       requestLayout();
20     }
21     //...省略不必要代码
22 }

它会调用requestLayout()方法,又去调用scheduleTraversals()方法,这是刷新view的一个相关方法,具体实现本文暂不分析。

1     public void requestLayout() {
2         checkThread();
3         mLayoutRequested = true;
4         scheduleTraversals();
5     }

到此可以看到notifyDataSetChanged是怎么一步步实现的了。

可以看到这个流程充分利用了观察者模式来激发view刷新。

view.setAdapter(adapter)传入的adapter就是被观察者,而观察者是GridView父类AbsListView的成员变量mDataSetObserver。所以刷新的界面被选定为此gridview。

这里的Observer相关的类都是由android实现的,但是与java实现思路相同。

Android源码与设计模式之notifyDataSetChanged()方法与观察者模式