Android设计模式 — 观察者模式
来源:互联网 发布:孕囊数据看男女已验证 编辑:程序博客网 时间:2024/05/29 03:36
我们考虑一个实际中比较常见的情况:我们进行数据显示的时候经常会用到ListView,并且会使用到分页加载机制,用于降低网络数据传输的延迟。那么当ListView中的数据改变的时候(比如加载下一页),我们会使用adapter.notifyDataSetChanged()来通知改变数据的显示,那么,这种机制是什么呢?显然,这是使用了“观察者模式”的设计思维。那么,对于GridView 甚至ViewPager是否也适用呢?我们以ListView来分析,慢慢分析...
我们来回顾一下我们使用ListView显示列表的步骤:
listView = (ListView) findViewById(R.id.listView); adapter = new MyAdapter();//MyAdapter为自定义的Adapter,继承自BaseAdapterlistView.setAdapter(adapter);//给ListView设置自定义的适配器
那么,第三行代码到底做了什么呢?我们来看看源码:(ListView.java)
public void setAdapter(ListAdapter adapter) { if (mAdapter != null && mDataSetObserver != null) { mAdapter.unregisterDataSetObserver(mDataSetObserver); } resetList(); mRecycler.clear(); //作者注:是否需要添加HeadView 和 FootView if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) { mAdapter = new HeaderViewListAdapter(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(); }可以看出来,其实setAdapter(adapter)做的是注册被观察者。
而当ListView显示的数据增加或者改变的时候,我们会调用adapter.notifyDataSetChanged()通知改变。再来看看notifyDataSetChanged()做了什么事情,查看源码(DataSetObservable.java)
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();//通知观察者更新 } }}但是mObservers是什么呢?继续追踪:
/** * Provides methods for registering or unregistering arbitrary observers in an {@link ArrayList}. * * This abstract class is intended to be subclassed and specialized to maintain * a registry of observers of specific types and dispatch notifications to them. * * @param T The observer type. */public abstract class Observable<T> { /** * The list of observers. An observer can be in the list at most * once and will never be null. */ protected final ArrayList<T> mObservers = new ArrayList<T>();//通知观察者列表 /** * 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其实是Observable里面的一个成员。然而,到底在什么地方实际进行了onChanged()了?查看源码(AbsListView.java):
public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher, ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener, ViewTreeObserver.OnTouchModeChangeListener, RemoteViewsAdapter.RemoteAdapterConnectionCallback { class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver { @Override public void onChanged() { super.onChanged(); if (mFastScroller != null) { mFastScroller.onSectionsChanged(); } } ... } ... }追踪super.onChanged()方法(AdapterView.java):
public abstract class AdapterView<T extends Adapter> extends ViewGroup { 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();//重新布局 } }}其中requestLayout()进行重新布局,完成数据更新操作。至此,adapter.notifyDataSetChanged()完成了数据的更新了。
下面,我们看看着一系列过程的类图:
我们看到,真正notifyDataSetChanged()是由AdapterDataSetObserver的onChanged()完成的。ListView继承自AbsListView,而GridView则(GridView.java):
public class GridView extends AbsListView {}
由此,可以断定GridView和ListView师出同门,同样适合上面所述的过程。
当然,如果你想探索的话,也可以研究一下ViewPager.java,看看它是否也是这样的呢?
- android 设计模式—— 观察者模式
- Android设计模式 — 观察者模式
- Android观察者设计模式
- android设计模式-观察者模式
- Android设计模式--观察者模式
- Android设计模式---观察者模式
- Android设计模式-观察者模式
- Android设计模式-----观察者模式
- Android设计模式--观察者模式
- 设计模式—观察者模式
- 设计模式—观察者模式
- 设计模式—观察者模式
- 设计模式—观察者模式
- 设计模式—观察者模式
- 设计模式—观察者模式
- 设计模式—观察者模式
- 设计模式—观察者模式
- 设计模式—观察者模式
- 陶仁贤学习笔记5
- 解决挂载ramdisk时Failed to execute /linuxrc.问题
- uboot之nandflash相关程序解释
- Java的数组
- flv在线录制、视频转换网站开发文档
- Android设计模式 — 观察者模式
- 硬件访问与混杂设备驱动
- 什么是反向代理
- 关于电商软件市场的格局点评
- poj 3486 简单dp
- Google地图API——IP映射为地址
- 2013年浙江某三甲医院的事业单位考试(信息科)笔试和面试
- JAVA try&&catch
- 数据结构 uva 101 - The Blocks Problem