赞
踩
观察者常用于订阅-发布系统,能够将观察者和被观察者进行解耦,降低两者之间的依赖;
定义:
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并被自动更新。
使用场景:
组合
关系;UML类图:
Subject:
抽象主题,被观察者的角色,抽象主题角色把所有观察者对象的引用保存到一个集合中,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察对象;ConcreteSubject:
具体主题,具体被观察者,该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发出通知;Observer:
抽象观察者,该角色是观察者的抽象类,它定义了一个更新接口,使得在得到主题的更改通知时更新自己;ConcreteObserver:
具体的观察者,该角色实现抽象观察者角色所定义的更新接口,以便在主题的状态发生变化时更新自己的状态;这里以关注微信公众号
进行举例,对于公众号
是被观察者,对于微信用户
则是观察者,微信用户订阅微信公众号后,公众号发布文章通知到微信用户,典型的发布-订阅模式;下面我们就用观察者模式来实现:
Observer
interface Observer<T> {
//定义文章更新方法
fun update(t: T)
}
Observable
open class Observable<T> { private val observers = arrayListOf<Observer<T>>() /** * 订阅被观察者 */ fun addObserver(observer: Observer<T>) { observers.add(observer) } /** * 解除订阅 */ fun removeObserver(observer: Observer<T>) { observers.remove(observer) } /** * 通知所有的观察者 */ fun notifyObservers(t: T) { for (observer in observers) { observer.update(t) } } }
WXUser
class WXUser(private val name: String) : Observer<String> {
override fun update(article: String) {
println("$name receive article:$article")
}
}
WXPublicObservable
class WXPublicObservable : Observable<String>() {
/**
* 更新公众号文章
*/
fun updateArticle(article: String) {
notifyObservers(article)
}
}
object Test { @JvmStatic fun main(args: Array<String>) { //定义微信用户 val user1 = WXUser("user1") val user2 = WXUser("user2") val wxPublicObservable = WXPublicObservable() //订阅公账号 wxPublicObservable.addObserver(user1) wxPublicObservable.addObserver(user2) //发布一篇文章 wxPublicObservable.updateArticle("互联网行业,迎来寒冬...") println("---------------------------") println("---------------------------") //user1取消订阅 wxPublicObservable.removeObserver(user1) wxPublicObservable.updateArticle("疫情何时才能结束...") } }
user1 receive article:互联网行业,迎来寒冬...
user2 receive article:互联网行业,迎来寒冬...
---------------------------
---------------------------
user2 receive article:疫情何时才能结束...
ListView.setAdapter
方法public void setAdapter(ListAdapter adapter) { //判断是否之前已经注册过观察者,如果注册过先注销,避免多次注册; if (mAdapter != null && mDataSetObserver != null) { mAdapter.unregisterDataSetObserver(mDataSetObserver); } ... super.setAdapter(adapter); if (mAdapter != null) { //创建一个数据集观察者进行注册 mDataSetObserver = new AdapterDataSetObserver(); mAdapter.registerDataSetObserver(mDataSetObserver); ... requestLayout(); }
我们紧着看下AdapterDataSetObserver
class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver { @Override public void onChanged() { super.onChanged(); if (mFastScroll != null) { mFastScroll.onSectionsChanged(); } } @Override public void onInvalidated() { super.onInvalidated(); if (mFastScroll != null) { mFastScroll.onSectionsChanged(); } } }
AdapterDataSetObserver
会继承DataSetObserver
,我们看下DataSetObserver
,典型的一个抽象观察者角色
public abstract class DataSetObserver {
public void onChanged() {
}
public void onInvalidated() {
}
}
通过上面的ListView.setAdapter
方法,就完成了观察者注册工作,我们在看下数据更新时,我们一般会调用notifyDataSetChanged方法
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); } public void notifyDataSetChanged() { mDataSetObservable.notifyChanged(); }
而mDataSetObservable
代码如下,显然,调用notifyDataSetChanged
方法实际上就是让被观察者去通知观察者数据发生了变化;
public class DataSetObservable extends Observable<DataSetObserver> { public void notifyChanged() { synchronized(mObservers) { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onChanged(); } } } public void notifyInvalidated() { synchronized (mObservers) { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onInvalidated(); } } } }
我们在回头看下AdapterDataSetObserver的onChanged()
方法都做了什么
class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver { @Override public void onChanged() { super.onChanged(); //重点看下 super.onChanged()方法 if (mFastScroll != null) { mFastScroll.onSectionsChanged(); } } @Override public void onInvalidated() { super.onInvalidated(); if (mFastScroll != null) { mFastScroll.onSectionsChanged(); } } }
super.onChanged()
对应AdapterDataSetObserver.onChanged()
方法
class AdapterDataSetObserver extends DataSetObserver { @Override public void onChanged() { mDataChanged = true; mOldItemCount = mItemCount; mItemCount = getAdapter().getCount(); if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null && mOldItemCount == 0 && mItemCount > 0) { AdapterView.this.onRestoreInstanceState(mInstanceState); mInstanceState = null; } else { rememberSyncState(); } checkFocus(); //最终会通过 requestLayout()完成listview所有数据更新 requestLayout(); }
小结:
Listview数据更新是典型的观察者设计模式
,在setAdapter方法里完成了观察者的注册工作,当调用notifyDataSetChanged方法的时候最终会通过requestLayout()完成所有数据更新!
优点:
缺点:
程序中包括一个被观察者,多个观察者对象,消息通知是遍历执行的,一个观察者卡顿,会影响整体的执行效率,这时候可以考虑采用异步的方式。
如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。