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实现思路相同。