Android源碼設(shè)計(jì)模式學(xué)習(xí)筆記-觀察者模式

觀察者模式主要是用于一對(duì)多模塊之間通信的解耦.
它的基本UML如下

image.png

Subject: 抽象主題,也就是被觀察者角色,抽象主題角色把所有觀察者對(duì)象的引用都保存到一個(gè)集合里,每個(gè)主題可以有任意數(shù)量的觀察者,抽象主題提供一個(gè)接口,可以增加和刪除觀察者對(duì)象.
ConcreteSubject: 具體主題,該角色將有關(guān)狀態(tài)存入具體,在具體主題的內(nèi)部狀態(tài)發(fā)生改變時(shí),給所有注冊(cè)過(guò)的觀察者發(fā)出通知,具體主題角色又叫做具體被觀察者(Concrete Observable)角色
Observer: 抽象觀察者,該角色是觀察者的抽象類(lèi),它定義了一個(gè)更新接口,使得主題更改通知時(shí)更新自己
ConcreteObserver: 具體的觀察者,該角色實(shí)現(xiàn)抽象觀察者角色定義的更新接口,以便在主題的狀態(tài)發(fā)生變化時(shí)更新自己的狀態(tài)
下面是一個(gè)觀察者模式的簡(jiǎn)單實(shí)現(xiàn):
開(kāi)發(fā)技術(shù)前沿網(wǎng)站(www.devtf.cn)是一個(gè)技術(shù)文章的網(wǎng)站,時(shí)常會(huì)更新新的技術(shù)文章后然后推送給訂閱者,我們來(lái)看看這個(gè)簡(jiǎn)單的需求如何通過(guò)觀察者模式去實(shí)現(xiàn).

public class Coder implements Observer{

    public String name;

    public Coder(String name) {
        this.name = name;
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("Hi, "+name+" , DevTechFrontier 更新啦,內(nèi)容 :"+arg);
    }

    @Override
    public String toString() {
        return "Coder{" +
                "name='" + name + '\'' +
                '}';
    }
}
public class DevTechFrontier extends Observable {
    public void postNewPublication(String content){
        //標(biāo)示狀態(tài)和內(nèi)容發(fā)生改變
        setChanged();
        //通知所有觀察者
        notifyObservers();
    }
}
DevTechFrontier devTechFrontier = new DevTechFrontier();
Coder misimple = new Coder("mr.simple");
Coder coder1 = new Coder("coder-1");
Coder coder2 = new Coder("coder-2");
Coder coder3 = new Coder("coder-3");
devTechFrontier.addObserver(coder1);
devTechFrontier.addObserver(coder2);
devTechFrontier.addObserver(coder3);
devTechFrontier.postNewPublication("新的一起開(kāi)發(fā)技術(shù)前線(xiàn)周報(bào)發(fā)布啦");

Observer和Observable是JDK中的內(nèi)置類(lèi)型,可見(jiàn)觀察者模式是非常重要的,這里Observer是抽象的觀察者角色,Coder扮演的是具體觀察者角色;Observable是抽象主題角色,DevTechFrontier則是具體的主題角色。DevTechFrontier通過(guò)addObserver添加Coder到它的觀察者列表中,一旦有文章更新便會(huì)通知所有列表中觀察者對(duì)象.

Android中的觀察者模式

ListView添加數(shù)據(jù)后,會(huì)調(diào)用Adapter的notifyDataSetChanged()方法,這是為什么呢?今天就來(lái)揭開(kāi)它的神秘面紗。
第一步我們就跟進(jìn)這個(gè)方法

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    //數(shù)據(jù)集觀察者
    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();
    }
}

我們?cè)俑M(jìn)mDataSetObservable.notifyChanged()中去看看:

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

調(diào)用notifyChanged后它會(huì)去通知mObservers這個(gè)觀察者集合數(shù)據(jù)發(fā)生改變。這些觀察者是ListView通過(guò)setAdapter方法設(shè)置Adapter產(chǎn)生的, 我們看看相關(guān)的代碼:

   @Override
    public void setAdapter(ListAdapter adapter) {
        //如果有了一個(gè)Adapter,那么先注銷(xiāo)該Adapter對(duì)應(yīng)的觀察者
        if (mAdapter != null && mDataSetObserver != null) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
        }
       super.setAdapter(adapter);
        if (mAdapter != null) {
            mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
            mOldItemCount = mItemCount;
            mItemCount = mAdapter.getCount();
            checkFocus();
            //注意這里,創(chuàng)建一個(gè)數(shù)據(jù)觀察
            mDataSetObserver = new AdapterDataSetObserver();
            //將這個(gè)觀察者注冊(cè)到Adapter中,實(shí)際上是注冊(cè)到mDataSetObservable中
            mAdapter.registerDataSetObserver(mDataSetObserver);
            //代碼省略
        } else {
            //代碼省略
        }
    }

這下我們觀察者,被觀察者都有了,它們?cè)趺催M(jìn)行注冊(cè)的也知道了,最后看看AdapterDataSetObserver到底是什么.它是AdapterView.java的一個(gè)內(nèi)部類(lèi)

class AdapterDataSetObserver extends DataSetObserver {
        private Parcelable mInstanceState = null;
        @Override
        public void onChanged() {
            mDataChanged = true;
            mOldItemCount = mItemCount;
            mItemCount = getAdapter().getCount();

            // Detect the case where a cursor that was previously invalidated has
            // been repopulated with new data.
            if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
                    && mOldItemCount == 0 && mItemCount > 0) {
                AdapterView.this.onRestoreInstanceState(mInstanceState);
                mInstanceState = null;
            } else {
                rememberSyncState();
            }
            checkFocus();
            requestLayout();
        }
}

當(dāng)ListView的數(shù)據(jù)發(fā)生變化時(shí),調(diào)用Adapter的notifyDataSetChanged函數(shù),這個(gè)函數(shù)又會(huì)調(diào)用DataSetObservable的notifyChanged函數(shù),這個(gè)函數(shù)會(huì)調(diào)用所有觀察者(AdapterDataSetObserver)的onChanged方法,在onChanged函數(shù)中又會(huì)調(diào)用ListView重新布局的函數(shù)使得Listview刷新界面,這就是一個(gè)觀察模式.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容