前言
首先先問(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)把我們的觀察者類寫一下帆喇。
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è)趯懹^察者類的時(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)試試吧毅该。