为了账号安全,请及时绑定邮箱和手机立即绑定

Android 设计模式情景分析——观察者模式

标签:
Android

观察者模式是一种使用频率非常高的模式,有时也被称作发布/订阅模式,属于行为型模式,它最常用的是 GUI 系统、订阅——发布系统,它一个重要作用就是解耦,使得它们之间的依赖性更小。观察者模式定义了对象间一种一对多的依赖关系,使得每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并被自动更新。

1.观察者模式的使用情景

关联行为场景;事件多级触发场景;跨系统的消息交换场景(如消息队列、事件总线的处理机制)。

2.程序中使用观察者模式的优缺点

-观察者模式
优点观察者和被观察者之间是耦合抽象,应对业务变化;增强了系统灵活性、可扩展性。
缺点开发调试变的比较复杂,Java中消息的通知是顺序执行,一个消息的卡顿会影响整体的执行效率,所以使用观察者模式还需要结合异步操作的方式。

3.观察者模式的UML类图

Subject:抽象主题,被观察(Observable)的角色;ConcreteSubject:具体主题;Observer:抽象观察者;ConcreteObserver:具体的观察者。

4.观察者模式的实现

观察者 Observer 和被观察者 Observable 是 JDK 中的内置类型。

1.创建观察者:

public class MyObserver implements Observer {
    private String name;    public MyObserver(String name) {        this.name = name;
    }    @Override
    public void update(Observable o, Object arg) {
        System.out.println(name + ", update:" + arg);
    }
}1234567891012345678910

2.创建被观察者:

public class MyObservable extends Observable {
    public void postNewPublication(String content) {        // 标识状态或者内容发生改变
        setChanged();        // 通知所有观察者
        notifyObservers(content);
    }
}

3.编写测试方法:

@Testpublic void test() throws Exception {    // 被观察者
    MyObservable observable = new MyObservable();    // 观察者
    MyObserver observer1 = new MyObserver("test1");
    MyObserver observer2 = new MyObserver("test2");
    MyObserver observer3 = new MyObserver("test3");
    MyObserver observer4 = new MyObserver("test4");    // 将观察者注册到被观察者对象的观察者列表中
    observable.addObserver(observer1);
    observable.addObserver(observer2);
    observable.addObserver(observer3);
    observable.addObserver(observer4);    // 发布消息
    observable.postNewPublication("new");
}

输出结果:

test4, update:new
test3, update:new
test2, update:new
test1, update:new

可以看到所有订阅了被观察者的观察者都接收到了更新消息,一对多的订阅——发布系统就完成了。

5.Android系统源代码中的应用情景

1.notifyDataSetChanged() 方法

我们在使用 ListView 添加数据后,都会调用 Adapter 的 notifyDataSetChanged() 方法来动态更新数据。

notifyDataSetChanged() 方法被定义在 BaseAdapter 中,BaseAdapter 就是一个观察者模式:

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    // 数据集观察者
    private final DataSetObservable mDataSetObservable = new DataSetObservable();    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
    }    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer);
    }    // 当数据集变化时,通知所有观察者
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }    // 代码省略}

我们跟进查看 mDataSetObservable.notifyChanged() 方法:

public class DataSetObservable extends Observable<DataSetObserver> {
    // 调用每个观察者的 onChanged() 方法来通知它们被观察者发生了变化
    public void notifyChanged() {        synchronized(mObservers) {            // 调用所有观察者的 onChanged() 方法
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }    // 代码省略}

这段代码就是在 mDataSetObservable.notifyChanged() 中遍历所有观察者,并且调用它们的 onChanged() 方法,从而告知观察者发生了变化。

那么这些观察者是哪里来的呢?其实是 ListView 通过 setAdapter() 方法设置 Adapter 产生的,我们来看看相关代码:

public class ListView extends AbsListView {
    // 代码省略
    @Override
    public void setAdapter(ListAdapter adapter) {        // 如果已经有了一个 Adapter,那么先注销该 Adapter 对应的观察者
        if (mAdapter != null && mDataSetObserver != null) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
        }        // 代码省略
        super.setAdapter(adapter);        if (mAdapter != null) {
            mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
            mOldItemCount = mItemCount;            // 获取数据的数量
            mItemCount = mAdapter.getCount();
            checkFocus();            // 这里注意:创建一个一个数据集观察者
            mDataSetObserver = new AdapterDataSetObserver();            // 将这个观察者注册到 Adapter 中,实际上是注册到 DataSetObservable 中
            mAdapter.registerDataSetObserver(mDataSetObserver);            // 代码省略
        } else {            // 代码省略
        }
        requestLayout();
    }    // 代码省略}

我们可以看到,在设置 Adapter 时会构建一个 AdapterDataSetObserver,也就是观察者,最后,将这个观察者注册到 Adapter 中。

到这里,我们就知道了,当 ListView 的数据发生变化时,调用 Adapter 的 notifyDataSetChanged() 方法,这个方法又调用 DataSetObservable 的 notifyChanged() 方法,这个方法又调用所有观察者(AdapterDataSetObserver)的 onChanged() 方法,在 onChanged() 方法中又会调用 ListView 重新布局的方法使得 ListView 刷新界面,这就是一个观察者模式。

原文链接:http://www.apkbus.com/blog-822724-68194.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消