ListView(AdapterView)涉及到的观察者模式 末蓝、 2022-05-27 00:57 138阅读 0赞 -------------------- # 前言 # > ListView在我们的实际开发中,出现的频率还是比较高的。今天我们来看看,listView是怎么监听数据变化的?当adapter(数据源)调用notifyDataSetChanged()方法(相当于数据源说,我要更新数据拉,你(adapterView)ui去更新界面吧),adapterView是怎么收到通知。你说listView关adapterView鸟事啊,listView和adapterView的继承关系如下: public class ListView extends AbsListView... public abstract class AbsListView extends AdapterView<ListAdapter> ... # 数据监听源码分析 # ## 回顾下ListView的使用方法 ## 1. 得到mListView控件; private ListView mListView = findViewById(R.id.listview); 2.创建adapter; class MyListAdapter extends BaseAdapter { private List<String> data; ''' } 3.给adapterView设置数据源(mAdapter = new MyListAdapter(List data)); mListView.setAdapter(mAdapter); ### 数据源(adapter)调用notifyDataSetChanged()方法 ### > 由2行,创建adapter的时候会创建DataSetObservable(被观察者对象);由21行,当adapter调用notifyDataSetChanged(),间接调用mDataSetObservable(被观察者对象)的notifyChanged()的方法;通过观察者模式,我们知道notifyChanged()方法肯定是通知所有的观察者; public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { private final DataSetObservable mDataSetObservable = new DataSetObservable(); public boolean hasStableIds() { return false; } public void registerDataSetObserver(DataSetObserver observer) { mDataSetObservable.registerObserver(observer); } public void unregisterDataSetObserver(DataSetObserver observer) { mDataSetObservable.unregisterObserver(observer); } /** * 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(); } ... } > 1.谁是观察者? > 2.观察者是什么时候加入到被观察者对象的? > > 我们看listView.setAdapter(ListAdapter)方法,由12-13行,先创建观察者(AdapterDataSetObserver)对象,然后通过mAdapter.registerDataSetObserver方法把该观察者注册到被观察者里面;我们回到BaseAdapter里面看看registerDataSetObserver方法;由22行mAdapter.registerDataSetObserver间接调用mDataSetObservable(系统提供的类)的对象registerObserver,该对象没有实现registerObserver方法,我们看到他的父类实现的registerObserver方法,跟我们之前预想的一样,通过registerObserver方法将观察者添加到mObservers集合中。 **1.谁是观察者?** 答:是在listView.setAdapter方法创建的AdapterDataSetObserver对象为观察者; **2.观察者是什么时候加入到被观察者对象的?** 答:是通过mAdapter.registerDataSetObserver方法间接通过mDataSetObservable.registerDataSetObserver(DataSetObservable对象没有重写该方法,具体实现在该父类)方法把观察者加入到被观察者对象的集合中。 @Override public void setAdapter(ListAdapter adapter) { .... super.setAdapter(adapter); if (mAdapter != null) { mAreAllItemsSelectable = mAdapter.areAllItemsEnabled(); mOldItemCount = mItemCount; mItemCount = mAdapter.getCount(); checkFocus(); mDataSetObserver = new AdapterDataSetObserver(); mAdapter.registerDataSetObserver(mDataSetObserver); .... } public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { private final DataSetObservable mDataSetObservable = new DataSetObservable(); ... public void registerDataSetObserver(DataSetObserver observer) { mDataSetObservable.registerObserver(observer); } ... } public class DataSetObservable extends Observable<DataSetObserver>.... 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); } } > 由上,我们知道了观察者被被观察者对象的结构关系。由1-11行,当调用mAdapter.notifyDataSetChanged方法,最终会调用观察者的onChanged()方法; 由21-36行,我们可以看到观察者onChanged()方法收到数据源更新的通知,确实去更新界面了。 public void notifyDataSetChanged() { mDataSetObservable.notifyChanged(); } public void notifyChanged() { synchronized(mObservers) { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onChanged(); } } } > > listView.setAdapter(ListAdapter adapter)方法: mDataSetObserver = new AdapterDataSetObserver(); // 该类是ListView的父类AbsListView类的父类AdapterView的内部类; 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(); } ... } # 总结 # > 观察者模式具体来分,可以分为推模式和拉模式。listView他是采用推模式。如果你还对观察者模式感兴趣,或者你还想了解观察者模式中的拉模式。你可以看看我之前写的···》[Java设计模式之观察者模式][Java] [Java]: https://mp.csdn.net/postedit/79822930
相关 观察者模式 什么是观察者模式 有人这么说 > 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 > > 这个主题对象在状态上发生变化时,会通知所有观 梦里梦外;/ 2022年07月20日 12:05/ 0 赞/ 238 阅读
相关 观察者模式 观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。 观察者模式图: ![输入图片说明][13105107_Mf 旧城等待,/ 2022年06月03日 02:41/ 0 赞/ 233 阅读
相关 ListView(AdapterView)涉及到的观察者模式 -------------------- 前言 > ListView在我们的实际开发中,出现的频率还是比较高的。今天我们来看看,listView是怎么监听数据变化的?当 末蓝、/ 2022年05月27日 00:57/ 0 赞/ 139 阅读
相关 观察者模式 前言 观察者模式还算一个比较好玩的设计模式,其实就是发布订阅模式,发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息。可以想象成消息中间件在系统中的作 墨蓝/ 2022年03月15日 06:48/ 0 赞/ 289 阅读
相关 观察者模式 类似于广播,目标对象的状态改变后,所有观察者的状态随之改变 步骤: 目标类中有一个属性是一个集合, 有一个注册方法,所有观察者使用前都要注册。 有一个 ╰半橙微兮°/ 2022年02月01日 15:43/ 0 赞/ 202 阅读
相关 观察者模式 前言 观察者模式又叫发布-订阅(Publish/Subscribe)模式 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个 本是古典 何须时尚/ 2021年12月09日 00:47/ 0 赞/ 317 阅读
相关 观察者模式 case ![18721752-ed32bda3ae538d1f.png][] image.png 非设计模式code SimpleWeatherDat 朱雀/ 2021年09月18日 07:26/ 0 赞/ 431 阅读
相关 观察者模式 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 意图:定义对象 系统管理员/ 2021年09月17日 01:36/ 0 赞/ 442 阅读
相关 观察者模式 15.观察者模式 ![70][] public abstract class Blog// 订阅号抽象类 { priva 布满荆棘的人生/ 2021年09月17日 00:04/ 0 赞/ 413 阅读
相关 观察者模式 一 点睛 定义 又被称为发布-订阅(Publish/Subscribe)模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态 ﹏ヽ暗。殇╰゛Y/ 2021年07月24日 14:52/ 0 赞/ 434 阅读
还没有评论,来说两句吧...