ListView(AdapterView)涉及到的观察者模式 末蓝、 2022-05-27 00:57 192阅读 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
相关 观察者模式 观察者模式 Observer 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 这个主题对象在状态上发生变化时,会通知所有观察者对 梦里梦外;/ 2022年08月03日 08:20/ 0 赞/ 47 阅读
相关 观察者模式 js观察者模式 <!DOCTYPE> <html> <head> <title> New Document </title> 刺骨的言语ヽ痛彻心扉/ 2022年07月21日 00:24/ 0 赞/ 39 阅读
相关 观察者模式 什么是观察者模式 有人这么说 > 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 > > 这个主题对象在状态上发生变化时,会通知所有观 梦里梦外;/ 2022年07月20日 12:05/ 0 赞/ 303 阅读
相关 观察者模式 场景描述: 一个气象站应用,可以实时获取温度、湿度和气压信息,气象站提供一个封装好的类WeatherData,该类有最新的气象信息,当这些信息发生变动的时候,类中的meas 叁歲伎倆/ 2022年06月14日 10:24/ 0 赞/ 197 阅读
相关 观察者模式 观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。 观察者模式图: ![输入图片说明][13105107_Mf 旧城等待,/ 2022年06月03日 02:41/ 0 赞/ 300 阅读
相关 ListView(AdapterView)涉及到的观察者模式 -------------------- 前言 > ListView在我们的实际开发中,出现的频率还是比较高的。今天我们来看看,listView是怎么监听数据变化的?当 末蓝、/ 2022年05月27日 00:57/ 0 赞/ 193 阅读
相关 观察者模式 什么是观察者模式? 简单的来说,观察者模式=出版者+订阅者。用比较书面的话来说的话是:定义了对象之间的一对多依赖,当一所对应的对象状态改变时,它的所有依赖者都会收到通知并 你的名字/ 2022年02月01日 13:53/ 0 赞/ 427 阅读
相关 观察者模式 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 意图:定义对象 系统管理员/ 2021年09月17日 01:36/ 0 赞/ 513 阅读
相关 观察者模式 对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 介绍 ... 小灰灰/ 2020年06月13日 05:42/ 0 赞/ 607 阅读
还没有评论,来说两句吧...