前言
首先先問(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)單就可以理解。

我們來(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)題。

從上圖可以看出,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)試試吧。