1. 模式定义
定义对象间一种一对多的依赖关系,每当一个对象改变状态时,则所有依赖于它的对象都会
得到通知并被自动更新。
2. Android 源码中的观察者模式应用
在 Android 的源码中,我们接触比较多的应该是 RecyclerView 和 ListView 了,和其搭配使用的 Adapter,有 刷新列表的 notifyDataSetChanged() 方法,那么,该方法是怎样刷新列表的呢?
首先我们要知道,观察者模式被观察者主要涉及三个操作:注册(添加)观察者、反注册观察者、通知观察者更新。
那 RecyclerView 是什么时候执行上述操作的呢?
RecyclerView.java
public void setAdapter(Adapter adapter) {
// bail out if layout is frozen
setLayoutFrozen(false);
setAdapterInternal(adapter, false, true);
requestLayout();
}
private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious,
boolean removeAndRecycleViews) {
if (mAdapter != null) {
mAdapter.unregisterAdapterDataObserver(mObserver);
mAdapter.onDetachedFromRecyclerView(this);
}
if (!compatibleWithPrevious || removeAndRecycleViews) {
removeAndRecycleViews();
}
mAdapterHelper.reset();
final Adapter oldAdapter = mAdapter;
mAdapter = adapter;
if (adapter != null) {
// 1. 看到此处
adapter.registerAdapterDataObserver(mObserver);
adapter.onAttachedToRecyclerView(this);
}
if (mLayout != null) {
mLayout.onAdapterChanged(oldAdapter, mAdapter);
}
mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
mState.mStructureChanged = true;
setDataSetChangedAfterLayout();
}
在上面的代码 adapter.registerAdapterDataObserver(mObserver); 中,可以看到这就是注册观察者了,此方法属于 RecyclerView 内部类 Adapter
public abstract static class Adapter {
public void registerAdapterDataObserver(AdapterDataObserver observer) {
mObservable.registerObserver(observer);
}
public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
mObservable.unregisterObserver(observer);
}
public final void notifyDataSetChanged() {
mObservable.notifyChanged();
}
}
当我们更新 RecyclerView 数据源的时候,执行了 adapter.notifyDataSetChanged(); 方法,那么此方法又做了什么工作呢?
RecyclerView 内部类 Adapter
public final void notifyDataSetChanged() {
mObservable.notifyChanged();
}
RecyclerView 内部类 AdapterDataObservable
static class AdapterDataObservable extends Observable {
public void notifyChanged() {
// 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();
}
}
}
RecyclerView 内部类 AdapterDataObserver
public abstract static class AdapterDataObserver {
public void onChanged() {
// Do nothing
}
}
还记得上面我们注册的方法入的参数吗?就是 一个 AdapterDataObserver 对象
adapter.registerAdapterDataObserver(mObserver);
那么,这个 mObserver 是何物?
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
RecyclerView 内部类 RecyclerViewDataObserver
private class RecyclerViewDataObserver extends AdapterDataObserver {
RecyclerViewDataObserver() {
}
@Override
public void onChanged() {
assertNotInLayoutOrScroll(null);
mState.mStructureChanged = true;
setDataSetChangedAfterLayout();
if (!mAdapterHelper.hasPendingUpdates()) {
requestLayout();
}
}
}
在此处,RecyclerView 会 requestLayout 等操作把列表给更新过来。
以上就是 RecyclerView 刷新列表的源码分析了,使用了观察者设计模式,对此,我们也可以使用该模式去处理一些有观察和被观察关系的场景。
3. 以公众号推送为例介绍观察者设计模式的精简用法
观察者:观察者需要被 push
观察者具有的操作接口
public interface IWXUser {
public void push(String article);
}
观察者
public class WXUser implements IWXUser {
private String name;
public WXUser(String name) {
this.name = name;
}
@Override
public void push(String article) {
System.out.println(name + " 收到了一篇文章:" + article);
}
}
被观察者:各种公众号
public class WXPublicObservable {
// 所有订阅的用户(公众号用户)
public List mWXUsers;
public WXPublicObservable(){
mWXUsers = new ArrayList<>();
}
/**
* 订阅
*/
public void register(IWXUser wxUser){
mWXUsers.add(wxUser);
}
/**
* 取消订阅
* @param wxUser
*/
public void unregister(IWXUser wxUser){
mWXUsers.remove(wxUser);
}
/**
* 更新文章
* @param article
*/
public void update(String article){
// 推送文章更新
for (IWXUser wxUser : mWXUsers) {
wxUser.push(article);
}
}
}
具体的被观察者
public class WXxxxObservable extends WXPublicObservable {
private String article;
public String getArticle() {
return article;
}
public void setArticle(String article) {
this.article = article;
// 通知更新,推送给微信用户
update(article);
}
}
3. 使用介绍
public class Client {
public static void main(String[] args){
// 微信公众号 - 具体的被观察者 - xxx
WXxxxObservable WXxxxObservable = new WXxxxObservable();
// 微信公众号 - 具体的观察者 vegen 和 小明同学
WXUser vegen = new WXUser("vegen");
WXUser xiaoming = new WXUser("小明同学");
// 微信公众号 - 用户订阅公众号
WXxxxObservable.register(vegen);
WXxxxObservable.register(xiaoming);
// 微信公众号 - 推送文章
WXxxxObservable.setArticle("我是文章巴拉巴拉1");
// 微信公众号 - 用户取消订阅公众号
WXxxxObservable.unregister(vegen);
// 微信公众号 - 推送文章
WXxxxObservable.setArticle("我是文章巴拉巴拉2");
}
}
vegen 和 小明同学 都能收到 文章巴拉巴拉1 的提示,vegen 后面取消了订阅,就只有 小明同学收到了 文章巴拉巴拉2 的提示。