[Android-Java]使用觀察者的正確姿勢(shì)

前言

首先先問(wèn)一個(gè)問(wèn)題,你在做Android開(kāi)發(fā)的時(shí)候有沒(méi)有被傳值整的蒙圈?例如Fragment之間的傳值,Activity之間的傳值(ActivityForResult比較常用),F(xiàn)ragment與Activity之間的傳值等等等等。
先列舉幾個(gè)簡(jiǎn)單的回傳例子吧。

1.Activity之間的傳值:Intent,startActivityForResult等等。
2.廣播傳值:BroadcastReceiver。
3.接口回調(diào)機(jī)制,也叫作代理模式,Android中經(jīng)常用到。
4.線程間傳值:Handler模式
5.Service與Activity之間的傳值:ServiceConnection

如果你是Android的新手,那這幾種東西都是很有必要了解的,其中比較難理解的應(yīng)該就是接口回調(diào)機(jī)制了。反正我講課的時(shí)候,基本上所有的學(xué)生在初次接觸之后,肯定蒙圈~

一、機(jī)制

那么言歸正傳,我們接下來(lái)呢,要講解的就是一種新的傳值方式,也是一種比較簡(jiǎn)單的方式----觀察者
首先我們來(lái)看一下觀察者的機(jī)制一幅圖,很簡(jiǎn)單就可以理解。

觀察者機(jī)制.png

我們來(lái)簡(jiǎn)單的講解一下上面的圖片:
A:被觀察者,信息的起點(diǎn),用來(lái)包裝信息
O:觀察者,信息的中轉(zhuǎn)站,用來(lái)傳遞信息
B:被改變者,信息的終點(diǎn),用來(lái)處理信息

第一步:先把被改變者B,放入觀察者O專門準(zhǔn)備的一個(gè)表中,注冊(cè)一下。
第二步:當(dāng)被觀察者A,觸發(fā)觀察者事件時(shí),發(fā)送通知給觀察者O。
第三步:觀察者O,會(huì)掃描自己的注冊(cè)表,如果發(fā)現(xiàn)有注冊(cè)者,也就是被改變者B存在的話,則進(jìn)行第四步。
第四步:觀察者O,把從被觀察者A處得到的信息,發(fā)送給被改變者B。

二、使用

說(shuō)了這么多,咱們來(lái)簡(jiǎn)單的看一個(gè)例子:從Activity傳值到Fragment。我覺(jué)得這是很多人都一直頭疼的一個(gè)問(wèn)題。

9834458E-C584-41D8-A8D6-59278836E0DF.png

從上圖可以看出,Activity中有一個(gè)輸入框和按鈕。Fragment中就很簡(jiǎn)單了,就只有一個(gè)TextView,我們現(xiàn)在想做的就是要在Activity的EditText輸入框中輸入內(nèi)容,當(dāng)點(diǎn)擊提交的時(shí)候,在Fragment的TextView中顯示Activity的EditText中輸入的內(nèi)容。
在看代碼之前呢,我們先來(lái)理清一下思路。確定一下誰(shuí)是被觀察者A,誰(shuí)是被改變者B,當(dāng)然,觀察者O是一個(gè)單獨(dú)的類,他們兩個(gè)肯定都不是。

被改變者:Fragment

被觀察者:Activity

好的,我們已經(jīng)確定了被觀察者和被改變者。下面我們先來(lái)把我們的觀察者類寫(xiě)一下。

public class MyObserverable extends Observable {

    public static MyObserverable observerable;

    // 單例:在所有內(nèi)存中,只存在一個(gè)此對(duì)象
    public static MyObserverable getObserverable() {
        if (observerable == null) {
            observerable = new MyObserverable();
        }
        return observerable;
    }

    public void setMessage(Object msg) {
        // 告訴觀察者對(duì)象,所觀察的內(nèi)容發(fā)生改變
        observerable.setChanged();
        // 刷新信息,或者信息傳遞
        observerable.notifyObservers(msg);
    }

}

這里我用的是一個(gè)單例,簡(jiǎn)單明確,并且很好用的哦~最基本的東西觀察者已經(jīng)做好了,在這里我們可以看到,觀察者在Java中是一個(gè)單獨(dú)的類,Observable。

下面就要使用這個(gè)觀察者類了,就遵循我們之前所說(shuō)的觀察者機(jī)制就好。

第一步:先把被改變者B,放入觀察者O專門準(zhǔn)備的一個(gè)表中,注冊(cè)一下。
public class Fragment01 extends Fragment implements Observer {
    TextView tv;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        View v = inflater.inflate(R.layout.f1, null);
        tv = (TextView) v.findViewById(R.id.textView1);
        // 注冊(cè)觀察者
        MyObserverable.getObserverable().addObserver(this);
        return v;
    }

    // 當(dāng)我們告訴觀察者,信息發(fā)生改變的時(shí)候,調(diào)用此方法
    @Override
    public void update(Observable observable, Object data) {
        tv.setText(data.toString());
    }
}

因?yàn)槲疫@里面是使用的單例類,所以我直接通過(guò)調(diào)用MyOserverable的靜態(tài)方法獲取的觀察者對(duì)象。

第二步:當(dāng)被觀察者A,觸發(fā)觀察者事件時(shí),發(fā)送通知給觀察者O。

public class MainActivity extends FragmentActivity {
    EditText et;
    Button btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et = (EditText) findViewById(R.id.et);
        btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

                String str = et.getText().toString();
                // 當(dāng)事件觸發(fā),通知觀察者
                MyObserverable.getObserverable().setMessage(str);

            }
        });
    }

}
第三步:觀察者O,會(huì)掃描自己的注冊(cè)表,如果發(fā)現(xiàn)有注冊(cè)者,也就是被改變者B存在的話,則進(jìn)行第四步。
public class MyObserverable extends Observable {

    ...
        // 掃描注冊(cè)表
    public void setMessage(Object msg) {
        // 告訴觀察者對(duì)象,所觀察的內(nèi)容發(fā)生改變
        observerable.setChanged();
        // 刷新信息,或者信息傳遞
        observerable.notifyObservers(msg);
    }

}

我們?cè)趯?xiě)觀察者類的時(shí)候,已經(jīng)完成了這一步。

第四步:觀察者O,把從被觀察者A處得到的信息,發(fā)送給被改變者B。
public class Fragment01 extends Fragment implements Observer {
    ...

    // 當(dāng)我們告訴觀察者,信息發(fā)生改變的時(shí)候,調(diào)用此方法
    @Override
    public void update(Observable observable, Object data) {
        tv.setText(data.toString());
    }
}

在第一步的代碼中其實(shí)我們已經(jīng)實(shí)現(xiàn)了處理方法:即實(shí)現(xiàn)Observer接口,并實(shí)現(xiàn)接口中的抽象方法update()。

這就是觀察者的使用步驟,是不是很簡(jiǎn)單?來(lái)試試吧。

最后編輯于
?著作權(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)容

  • 專業(yè)考題類型管理運(yùn)行工作負(fù)責(zé)人一般作業(yè)考題內(nèi)容選項(xiàng)A選項(xiàng)B選項(xiàng)C選項(xiàng)D選項(xiàng)E選項(xiàng)F正確答案 變電單選GYSZ本規(guī)程...
    小白兔去釣魚(yú)閱讀 10,554評(píng)論 0 13
  • 面試題總結(jié) 通用 安卓學(xué)習(xí)途徑, 尋找資料學(xué)習(xí)的博客網(wǎng)站 AndroidStudio使用, 插件使用 安卓和蘋(píng)果的...
    JingBeibei閱讀 1,873評(píng)論 2 21
  • Java基礎(chǔ) 什么是重載,什么是重寫(xiě)?有什么區(qū)別?重載(Overload):(1)Overloading是一個(gè)類中...
    勤息嘻嘻嘻閱讀 701評(píng)論 0 1
  • 最近剛從舊公司離職,為面試在做準(zhǔn)備,因?yàn)槠綍r(shí)開(kāi)發(fā)CV大法用得比較多,很多基礎(chǔ)知識(shí)掌握得不是很牢靠以及很多工具框架只...
    黎清海閱讀 2,330評(píng)論 1 19
  • 一、查看內(nèi)存、cpu情況 參考鏈接[https://blog.csdn.net/mydriverc2/articl...
    WAHAHA402閱讀 1,453評(píng)論 0 1

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