1. 程式人生 > >利用觀察者(Observer)和被觀察者(Observable)實現監聽操作

利用觀察者(Observer)和被觀察者(Observable)實現監聽操作

老規矩上圖:

這裡寫圖片描述

第一步:上佈局檢視只貼一部分

 <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#f6534c"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height
="wrap_content" android:layout_marginLeft="20dp" android:layout_marginTop="20dp" android:orientation="horizontal">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text
="總財富" android:textColor="#fcc7c6" />
<!--註冊checkBox為被觀察者--> <com.example.hxl.observerdemo.CheckBoxObservable android:id="@+id/checkBoxObservable" android:layout_width="wrap_content" android:layout_height
="wrap_content" android:layout_marginLeft="5dp" android:button="@drawable/bg_checkbox_sel" />
<!-- checkBox:xml中內部實現點選事件 android:button="@drawable/bg_checkbox_sel"--> </LinearLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:id="@+id/my_assert_total_account_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <!--讓總財富下的textView,成為觀察者--> <com.example.hxl.observerdemo.TextViewObserver android:id="@+id/my_assert_total_account" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:layout_marginLeft="20dp" android:layout_marginTop="10dp" android:text="0.00" android:textColor="#fccbca" android:textSize="32sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:paddingBottom="2dp" android:text="(交易確認中或暫無資產)" android:textColor="#ffffff" android:textSize="12sp" /> </LinearLayout> <ImageView android:id="@+id/total_account_hider" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:src="@drawable/wealth_hidden" android:visibility="invisible" /> </RelativeLayout> </LinearLayout>

第二步:被觀察者

/**
 * 實現觀察者模式的被觀察者
 * 讓checkBox成為被觀察者
 */
public class CheckBoxObservable extends CheckBox implements CompoundButton.OnCheckedChangeListener{
    private ObservableInner mObservable;
    public CheckBoxObservable(Context context) {
        super(context);
        init();
    }

    public CheckBoxObservable(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CheckBoxObservable(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void hide() {
        // 狀態改變 ,資料改變
        setChanged();
        //傳送資訊告訴觀察者,只有為真時,才會呼叫觀察者的update方法
        notifyObservers(true);
    }

    private void show() {
        setChanged();  // 狀態改變,必須呼叫
        notifyObservers(false);
    }

    //初始化操作
    public void init() {
        //建立被觀察者
        mObservable = new ObservableInner();
        //設定被觀察者狀態改變監聽
        setOnCheckedChangeListener(this);
    }

    //新增觀察者
    public void addObserver(Observer observer){
        mObservable.addObserver(observer);
    }

    //刪除某一個具體的觀察者
    public void deleteObserver(Observer observer) {
        mObservable.deleteObserver(observer);
    }

    //刪除所有的觀察者
    public void deleteObservers() {
        mObservable.deleteObservers();
    }

    //返回列表中所有的新增觀察者
    public int countObservers(){
        return mObservable.countObservers();
    }

    //通知重新整理所有的觀察者
    public void notifyObservers(){
        mObservable.notifyObservers();
    }

    public void notifyObservers(Object data){
        mObservable.notifyObservers(data);
    }

    public boolean hasChanged() {
        return mObservable.hasChanged();
    }

    protected void setChanged() {
        mObservable.setChanged();
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (isChecked) {
            hide();
        } else {
            show();
        }
    }

    //被觀察者(Observable)   觀察者(Observer)
    private class ObservableInner extends Observable {
       //自定義setChange方法,實現調系統方法
        public void setChanged() {
            super.setChanged();
        }
    }
}

第三步:觀察者

/**
 * 實現觀察者模式的觀察者
 * 讓text實現成為觀察者
 *Observer接收到通知的順序是越晚加入列表的越先通知。
 */
public class TextViewObserver extends TextView implements Observer{
    private static final String DEFAULT_HIDER = "******";

    private String mOrignalContent = "";
    //設定隱藏的內容
    private String mHiderContent = DEFAULT_HIDER;
    //是否隱藏
    private boolean mIsHideContent = false;
    private OnShownListener mOnShownListener;
    private OnHiderListener mOnHiderListener;

    public TextViewObserver(Context context) {
        super(context);
        mOrignalContent =  getText().toString();
    }

    public TextViewObserver(Context context, AttributeSet attrs) {
        super(context, attrs);
        mOrignalContent =  getText().toString();
    }

    public TextViewObserver(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mOrignalContent =  getText().toString();
    }

    //接收到被觀察者的訊號後,開始執行具體操作
    @Override
    public void update(Observable o, Object arg) {
        mIsHideContent = (boolean)arg;
        if (mIsHideContent) {
            setText(mHiderContent);
            if (mOnHiderListener != null) {
                //回撥方法,用於銅幣狀態控制
                mOnHiderListener.onHider();
            }
        } else {
            setText(mOrignalContent);
            if (mOnShownListener != null) {
                mOnShownListener.onShown();
            }
        }
    }

    /**
     * 注意:需要呼叫此方法才能實現隱藏效果,若直接呼叫setText()方法,則實現不了
     * @param text
     */
    public void setTextExtension(String text) {
        mOrignalContent = String.valueOf(text);
        if (!mIsHideContent) {  // 非隱藏狀態下,更新內容
            setText(mOrignalContent);
        }
    }

    /**
     * 注意:需要呼叫此方法才能實現隱藏效果,若直接呼叫setText()方法,則實現不了
     * @param text
     */
    public void setTextExtension(CharSequence text) {
        mOrignalContent = String.valueOf(text);
        if (!mIsHideContent) {  // 非隱藏狀態下,更新內容
            setText(mOrignalContent);
        }
    }

    public void setHiderContent(String mHiderContent) {
        this.mHiderContent = mHiderContent;
    }

    public String getHiderContent() {
        return this.mHiderContent;
    }

    public void setOnShownListener(OnShownListener onShownListener) {
        this.mOnShownListener = onShownListener;
    }

    public void setOnHiderListener(OnHiderListener onHiderListener) {
        this.mOnHiderListener = onHiderListener;
    }

    public interface OnShownListener {
        public void onShown();
    }

    public interface OnHiderListener {
        public void onHider();
    }
}

第四步:主體部分實現

CheckBoxObservable checkBoxObservable;
    TextViewObserver myAssertTotalAccount;
    TextViewObserver regularInvestmentAccount;
    TextViewObserver tongbaoAccount;

    LinearLayout myAssertTotalAccountLayout;
    ImageView totalAccountHider;

//新增觀察者
        checkBoxObservable.addObserver(myAssertTotalAccount);
        //觀察者設定隱藏監聽
        myAssertTotalAccount.setOnHiderListener(new TextViewObserver.OnHiderListener() {
            @Override
            public void onHider() {
                //此時不能設定為Gone,會引起佈局的變化
                myAssertTotalAccountLayout.setVisibility(View.INVISIBLE);
                //設定銅寶圖片狀態
                totalAccountHider.setVisibility(View.VISIBLE);
            }
        });
        //觀察者設定顯示監聽
        myAssertTotalAccount.setOnShownListener(new TextViewObserver.OnShownListener() {
            @Override
            public void onShown() {
                myAssertTotalAccountLayout.setVisibility(View.VISIBLE);
                //此時不能設定為Gone,會引起佈局的變化
                totalAccountHider.setVisibility(View.INVISIBLE);
            }
        });
        //新增其他觀察者
        checkBoxObservable.addObserver(regularInvestmentAccount);
        checkBoxObservable.addObserver(tongbaoAccount);
        checkBoxObservable.addObserver(myBalanceAccount);

最後別忘了:解除被觀察者和觀察者之間的繫結

@Override
    public void onDestroyView() {
        super.onDestroyView();
        //解綁
        ButterKnife.unbind(this);
        if (checkBoxObservable != null) {
            //解除觀察者
            checkBoxObservable.deleteObservers();
        }
    }

附帶:CheckBox的button點選選擇

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/wealth_eye_close" android:state_checked="true"/>
    <item android:drawable="@drawable/wealth_eye_open" android:state_checked="false"/>
</selector>

以上,就可以實現