Androidオブザーバーモード

8616 ワード

コンセプト:
オブジェクト間の1対のマルチ依存性が定義され、1つのオブジェクトがステータスを変更すると、すべての依存者が通知を受け取り、自動的に更新されます.
4つの要素(自己定義):
オブザーバ、オブザーバ、登録タイミング、メソッド呼び出し
2つの実装方法:
観察者は受動的にメッセージ1を受け取る.オブジェクトインタフェースの作成
 public interface Subject{
        public void registerObserver(Observer o);
        public void removeObserver(Observer o);
        public void notifyObservers();
    }

被観察者の実現ロジック
     public class WeatherData implements Subject{

        private ArrayList observers;
        //  
        private String temperature;
        //  
        private String humidity;
        //  
        private String pressure;

        public WeatherData() {
            observers=new ArrayList();
        }
        /**
         *   
         */
        public void registerObserver(Observer o) {
            observers.add(o);
        }
        /**
         *     
         */
        public void removeObserver(Observer o) {
            if(observers.indexOf(o)>=0){
                observers.remove(o);
            }
        }
        /**
         *      
         */
        public void notifyObservers() {
            for(Observer o:observers){
                o.update(temperature, humidity, pressure);
            }
        }
        /**
         *      ,     
         * @param temperature
         * @param humidity
         * @param pressure
         */
        public void setNewData(String temperature,String humidity,String pressure){
            this.temperature=temperature;
            this.humidity=humidity;
            this.pressure=pressure;
            notifyObservers();
        }
    }

notifyObserversメソッドでは、オブジェクトのセットを巡ってupdateメソッドが呼び出され、変化した値がオブジェクトに表示されます.2.オブザーバインタフェースの作成
 public interface Observer{
        public void update(String temperature,String humidity,String pressure);
    }

3.観察者の実現と登録は、それぞれの観察者の登録タイミングが異なり、ここでは観察者をインスタンス化する際に登録する
public class CurrentCodition implements Observer {
        private Subject weaterData;

        public CurrentCodition(Subject weaterData) {
            this.weaterData = weaterData;
            weaterData.registerObserver(this);
        }
        @Override
        public void update(String temperature,String humidity,String pressure) {
        //      
        }
    }

4.更新の呼び出し
WeatherData weatherData=new WeatherData();
Observer1 observer1=new Observer1(weatherData);
weatherData.setNewData("10", "20", "30");

観察者は自発的にメッセージ1を受け取る.被観察者は、上記に基づいてgetメソッドを追加し、観察者に所望のデータを得る方法を提供する.
public String getTemperature() {
        return temperature;
    }
    public String getHumidity() {
        return humidity;
    }
    public String getPressure() {
        return pressure;
    }

2.観察者は観察者のupdateメソッドを修正し、WeatherDataインスタンスから自分の欲しいデータを直接取得し、不要なものはgetを使わない
public void update(Observable o, Object arg) {
        if(o instanceof WeatherData){
            WeatherData data=(WeatherData)o;
            this.humidity=data.getHumidity();
            this.pressure=data.getPressure();
            this.temperature=data.getTemperature();
        }
        System.out.println("      ,    ");
    }

Androidでの使用
1.setOnClickListener()一対一を実現する観察者モードまず方法の中でどのように実現ロジックがあるかを直接見る
 public void setOnClickListener(@Nullable OnClickListener l) {
        if (!isClickable()) {
            setClickable(true);
        }
        getListenerInfo().mOnClickListener = l;
    }

setOnClickListener()の過程で直接OnClickListenerをListener Infoの変数に割り当てて、それからこの変数はいつ呼び出されますか、次に見てみましょう
public boolean performClick() {
        final boolean result;
        final ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            li.mOnClickListener.onClick(this);
            result = true;
        } else {
            result = false;
        }

        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
        return result;
    }

performClick()メソッドでonClickメソッドを直接呼び出すのを見ることができますが、それは誰がperformClick()メソッドを呼び出すのか、検索によってViewクラスにナビゲートすると、以下のコードロジックが表示されます.
public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
        if (isNestedScrollingEnabled()
                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
                || action == R.id.accessibilityActionScrollUp
                || action == R.id.accessibilityActionScrollLeft
                || action == R.id.accessibilityActionScrollDown
                || action == R.id.accessibilityActionScrollRight)) {
            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
                return true;
            }
        }

        switch (action) {
            case AccessibilityNodeInfo.ACTION_CLICK: {
                if (isClickable()) {
                    performClick();
                    return true;
                }
            } break;
            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
                if (isLongClickable()) {
                    performLongClick();
                    return true;
                }
            } break;

コードの中で1つのswitch条件を用いて判断し、異なる操作によって相応の論理を実行し、ここを見て明らかにすべきである.Viewという被観察者は、状態の変化を傍受した後、登録されたonClickListenerの中のonClick観察者メソッドを呼び出し、相応の操作を完了し、1対1のモニタリングであるため、集合の遍歴操作はない.2.listView一対多のオブザーバーモードを実現まずは被オブザーバーの実現方式を見よう
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    private final DataSetObservable mDataSetObservable = new DataSetObservable();
    public boolean hasStableIds() {
        return false;
    }
    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
    }
    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer);
    }
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }

BaseAdapterは,DataSetObservable(被観察者)クラスを直接継承するのではなく,組合せによって変数として用いられることがコードから分かる.次に、listViewの親AdapterViewで観察者の実装クラスを見つけます.
    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();
        }

        @Override
        public void onInvalidated() {
            mDataChanged = true;

            if (AdapterView.this.getAdapter().hasStableIds()) {
                // Remember the current state for the case where our hosting activity is being
                // stopped and later restarted
                mInstanceState = AdapterView.this.onSaveInstanceState();
            }

            // Data is invalid so we should reset our state
            mOldItemCount = mItemCount;
            mItemCount = 0;
            mSelectedPosition = INVALID_POSITION;
            mSelectedRowId = INVALID_ROW_ID;
            mNextSelectedPosition = INVALID_POSITION;
            mNextSelectedRowId = INVALID_ROW_ID;
            mNeedSync = false;

            checkFocus();
            requestLayout();
        }

        public void clearSavedState() {
            mInstanceState = null;
        }
    }

そしてメソッドの呼び出しを見て
public void notifyChanged() {
    synchronized(mObservers) {
    for (int i = mObservers.size() - 1; i >= 0; i--) {
            mObservers.get(i).onChanged();
        }
    }
}

データ更新があるたびに、このメソッドが呼び出されてデータがリフレッシュされ、メソッドには観察者の集合が遍歴し、統一された実装メソッドonChanged()が呼び出されてデータのリフレッシュが実現されることがわかります.最后に登录して、実は毎回setAdapter()は登录の过程で、コードは贴らないで、兴味のある小さい仲间は自分でソースコードを见ることができます!!!やはりおかず鸟ですが、问题があれば「笑颜」を指摘してくださいね~