作业三-观察者模式

  • 观察者模式简介

    • 观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。
    • 在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

 

  • 观察者模式结构


  • 观察者模式包含的角色

    • 抽象被观察者角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
    • 抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
    • 具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
    • 具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。

 

  • Android中的观察者模式

  • android源码中也有很多使用了观察者模式,比如OnClickListener、ContentObserver、android.database.Observable等;还有组件通讯库RxJava、RxAndroid、EventBus;在这里将拿我们最常用的Adapter的notifyDataSetChanged()方法来举例:

  当我们用ListView的时候,数据发生变化的时候我们都会调用Adapter的notifyDataSetChanged()方法,这个方法定义在BaseAdaper中,我们来看看BaseAdaper的部分源码:

 1 public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
 2 
 3     //数据集观察者
 4     private final DataSetObservable mDataSetObservable = new DataSetObservable();
 5 
 6     public boolean hasStableIds() {
 7         return false;
 8     }
 9 
10     public void registerDataSetObserver(DataSetObserver observer) {
11         mDataSetObservable.registerObserver(observer);
12     }
13 
14     public void unregisterDataSetObserver(DataSetObserver observer) {
15         mDataSetObservable.unregisterObserver(observer);
16     }
17 
18     /**
19      * 当数据集变化时,通知所有观察者
20      */
21     public void notifyDataSetChanged() {
22         mDataSetObservable.notifyChanged();
23     }

  BaseAdapter用的是观察者模式,BaseAdapter是具体被观察者,接下来看看mDataSetObservable.notifyChanged():

1 public class DataSetObservable extends Observable<DataSetObserver> {
2     public void notifyChanged() {
3         synchronized(mObservers) {
4             for (int i = mObservers.size() - 1; i >= 0; i--) {
5                 mObservers.get(i).onChanged();
6             }
7         }
8     }

  我们看到了mObservers,这就是观察者的集合,这些观察者是在ListView通过setAdaper()设置Adaper时产生的:

 1 @Override
 2     public void setAdapter(ListAdapter adapter) {
 3         if (mAdapter != null && mDataSetObserver != null) {
 4             mAdapter.unregisterDataSetObserver(mDataSetObserver);
 5         }
 6         ...
 7         super.setAdapter(adapter);
 8 
 9         if (mAdapter != null) {
10             mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
11             mOldItemCount = mItemCount;
12             mItemCount = mAdapter.getCount();
13             checkFocus();
14             //创建数据观察者
15             mDataSetObserver = new AdapterDataSetObserver();
16             //注册观察者
17             mAdapter.registerDataSetObserver(mDataSetObserver);
18 
19             ...
20         }

 

  接下来看看观察者AdapterDataSetObserver中处理了什么:

 1 class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
 2         @Override
 3         public void onChanged() {
 4             super.onChanged();
 5             if (mFastScroller != null) {
 6                 mFastScroller.onSectionsChanged();
 7             }
 8         }
 9 
10         @Override
11         public void onInvalidated() {
12             super.onInvalidated();
13             if (mFastScroller != null) {
14                 mFastScroller.onSectionsChanged();
15             }
16         }
17     }

  再看看AdapterDataSetObserver的父类AdapterView的AdapterDataSetObserver:

 1 class AdapterDataSetObserver extends DataSetObserver {
 2         private Parcelable mInstanceState = null;
 3         @Override
 4         public void onChanged() {
 5             mDataChanged = true;
 6             mOldItemCount = mItemCount;
 7             mItemCount = getAdapter().getCount();
 8             if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
 9                     && mOldItemCount == 0 && mItemCount > 0) {
10                 AdapterView.this.onRestoreInstanceState(mInstanceState);
11                 mInstanceState = null;
12             } else {
13                 rememberSyncState();
14             }
15             checkFocus();
16             //重新布局
17             requestLayout();
18         }
19 
20         ...
21 
22         public void clearSavedState() {
23             mInstanceState = null;
24         }
25     }

  我们看到在onChanged()方法中调用了requestLayout()方法来重新进行布局。当ListView的数据发生变化时,我们调用Adapter的notifyDataSetChanged()方法,这个方法又会调用观察者们(AdapterDataSetObserver)的onChanged()方法,onChanged()方法又会调用requestLayout()方法来重新进行布局。

  • 通过分析我们得知:
    • 通过给setAdapter(adapter)方法进行观察者的注册。
    • 被观察者通过notifyDataSetChanged()方法通知观察者进行处理。
    • AdapterDataSetObserver继承自AdapterView内部类AdapterDataSetObserver,并交由它来进行AdapterView组件的重新布局。

  使用观察者模式,最大的好处就是实现了代码解耦,被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。

  • 跳转链接: https://github.com/aosp-mirror/platform_frameworks_base/blob/a01c77a499d9037a21b8ea1a5cd1df1a7dea7f25/core/java/android/widget/BaseAdapter.java#L53
posted @ 2018-10-24 18:29  eva194  阅读(175)  评论(0)    收藏  举报