Android源码设计模式解析与实战(十二)
Android源码设计模式解析与实战(十二)
xingjm8511 发表于10个月前
Android源码设计模式解析与实战(十二)
  • 发表于 10个月前
  • 阅读 4
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 解决、解耦的钥匙——观察者模式

1. 观察者模式定义

定义对象间一种一对多的依赖关系,使的每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新

2. 观察者模式的使用场景

(1) 关联行为场景,需要注意的是,关联行为是可拆分的,而不是"组合"关系。

(2) 事件多级触发场景。

(3) 跨系统的消息交换场景,如消息队列、事件总线的处理机制。

3. Android源码分析

ListView最重要的一个功能就是Adapter,通常我们往ListView添加数据后,都会调用Adapter的notifyDataSetChanged()方法。

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();
    }
}
/**
 * 数据集观察者
 */
public class DataSetObservable extends Observable<DataSetObserver> {
    /**
     * 调用每个观察者的onChanged函数来通知它们被观察者发生了变化
     */
    public void notifyChanged() {
        // 调用所有观察者的onChanged方式
        for (int i = mObservers.size() - 1; i >= 0; i--) {
            mObservers.get(i).onChanged();
        }
    }
    ......
}

这些观察者就是ListView通过setAdapter方法设置产生的。

public void setAdapter(ListAdapter adapter) {
    // 如果已经有一个Adapter,那么先注销该Adapter对应的观察者
    if (mAdapter != null && mDataSetObserver != null) {
        mAdapter.unregisterDataSetObserver(mDataSetObserver);
    }
    ......
    super.setAdapter(adapter);
    if (mAdapter != null) {
        ......
        mDataSetObserver = new AdapterDataSetObserver();
        mAdapter.registerDataSetObserver(mDataSetObserver);
    } else {
        ......
    }
}

总结下,AdapterView中有一个内部类AdapterDataSetObserver,在ListView中设置Adapter时会构建一个AdapterDataSetObserver,并且注册到Adapter中。而Adapter中包含一个数据集看观察者DataSetObservable,在数据集发生变化时,开发者手动调用Adapter.notifyDataSetChanged,继而会遍历所有观察者的onChanged函数,然后调用ListView的requestLayout()重新布局,更新用户界面。

共有 人打赏支持
粉丝 18
博文 109
码字总数 45031
×
xingjm8511
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: