本文共 5652 字,大约阅读时间需要 18 分钟。
源码是谷歌攻城狮的精髓,我们要向他们学习,提高自己,只能翱翔于源码的海洋,才能明白谷歌攻城狮的强大。观察者在我们开发过程中使用的是相当的多,那么在源码层就使用的更多了。之前有做过观察者模式的学习笔记。这里就不重复一遍了。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = new ListView(this); MyAdapter myAdapter = new MyAdapter(); //注册观察者 listView.setAdapter(myAdapter); //这里通知观察者更新数据 myAdapter.notifyDataSetChanged(); } private class MyAdapter extends BaseAdapter{ @Override public int getCount() { return 0; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { return null; } }}
我们在使用ListView的时候,一般是这样使用的。那么我们先从setAdapter开始。看看是如何注册观察者的。
@Override public void setAdapter(ListAdapter adapter) { if (mAdapter != null && mDataSetObserver != null) { mAdapter.unregisterDataSetObserver(mDataSetObserver); } resetList(); mRecycler.clear(); if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) { mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, adapter); } else { mAdapter = adapter; } mOldSelectedPosition = INVALID_POSITION; mOldSelectedRowId = INVALID_ROW_ID; // AbsListView#setAdapter will update choice mode states. super.setAdapter(adapter); if (mAdapter != null) { mAreAllItemsSelectable = mAdapter.areAllItemsEnabled(); mOldItemCount = mItemCount; mItemCount = mAdapter.getCount(); checkFocus(); mDataSetObserver = new AdapterDataSetObserver(); mAdapter.registerDataSetObserver(mDataSetObserver); mRecycler.setViewTypeCount(mAdapter.getViewTypeCount()); int position; if (mStackFromBottom) { position = lookForSelectablePosition(mItemCount - 1, false); } else { position = lookForSelectablePosition(0, true); } setSelectedPositionInt(position); setNextSelectedPositionInt(position); if (mItemCount == 0) { // Nothing selected checkSelectionChanged(); } } else { mAreAllItemsSelectable = true; checkFocus(); // Nothing selected checkSelectionChanged(); } requestLayout(); }mDataSetObserver = new AdapterDataSetObserver();mAdapter.registerDataSetObserver(mDataSetObserver);创建了一个观察者,并且注册了。注册方法里的逻辑是什么呢。registerDataSetObserver调用的BaseAdapter的。
private final DataSetObservable mDataSetObservable = new DataSetObservable(); public void registerDataSetObserver(DataSetObserver observer) { mDataSetObservable.registerObserver(observer); }
在BaseAdapter的registerDataSetObserver中,创建了一个被观察者对象,调用被观察者的registerObserver进行绑定。
/** * Adds an observer to the list. The observer cannot be null and it must not already * be registered. * @param observer the observer to register * @throws IllegalArgumentException the observer is null * @throws IllegalStateException the observer is already registered */ 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); } }mObservers是一个集合,用于存观察者。进行管理,这里就是一对多的关系建立。注册完成之后,那么我们什么时候通知观察者更新数据呢?就是调用notifyDataChanged的时候。在BaseAdapter中,查看notifyDataChanged
/** * Notifies the attached observers that the underlying data has been changed * and any View reflecting the data set should refresh itself. */ public void notifyDataSetChanged() { mDataSetObservable.notifyChanged(); }继续在DataSetObservable中,查看notifyChanged
/** * Invokes {@link DataSetObserver#onChanged} on each observer. * Called when the contents of the data set have changed. The recipient * will obtain the new contents the next time it queries the data set. */ public void notifyChanged() { synchronized(mObservers) { // since onChanged() is implemented by the app, it could do anything, including // removing itself from {@link mObservers} - and that could cause problems if // an iterator is used on the ArrayList {@link mObservers}. // to avoid such problems, just march thru the list in the reverse order. for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onChanged(); } } }对存储的观察进行遍历,依次通知观察者进行更新,调用onChanged。那么观察者在ListView中的使用就这么多,当然ListView中使用的设计模式很多,还有像模板方法等等。有兴趣的可以自己研究研究。
转载地址:http://duqxi.baihongyu.com/