一、簡(jiǎn)介
在進(jìn)行Android開(kāi)發(fā)過(guò)程中我們知道Activity的重要性,但是自android3.0之后,android中出現(xiàn)的Fragment重要性其實(shí)不亞于Activity,今天簡(jiǎn)單的介紹一下Fragment之間進(jìn)行數(shù)據(jù)傳遞的三種方式。
二、準(zhǔn)備工作
step 1:創(chuàng)建一個(gè)Activity,命名為MainActivity,對(duì)應(yīng)的布局文件如下(只截取核心部分):
<FrameLayout
android:id="@+id/fl_menu"
android:layout_width="0dp"
android:layout_weight="1"
android:background="#20ff0000"
android:layout_height="match_parent"/>
<FrameLayout
android:id="@+id/fl_main"
android:layout_width="0dp"
android:layout_weight="2"
android:background="#2500ff00"
android:layout_height="match_parent"/>
step2:創(chuàng)建兩個(gè)Fragment分別為MenuFragment和MainFragment,對(duì)應(yīng)的布局如下: MenuFragment的核心布局:
<ListView
android:id="@+id/lv_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
MainFragment核心布局:
<Button
android:id="@+id/bt_main"
android:background="#ff0"
android:layout_width="200dp"
android:layout_height="200dp"
android:text="根據(jù)條目改變內(nèi)容"
android:layout_centerInParent="true"/>
step3:兩個(gè)Fragment里面各自將布局引進(jìn)(onCreateView()方法中)(具體代碼請(qǐng)參考源碼),需要注意的是MenuFragment里面是一個(gè)ListView,這里手動(dòng)添加了5個(gè)數(shù)據(jù)填充進(jìn)去; step4:在MainActivity的onCreate()方法中引入這兩個(gè)Fragment:
MenuFragment menuFragment = new MenuFragment();
MainFragment mainFragment = new MainFragment();
//將上面的兩個(gè)Fragment添加進(jìn)來(lái)
getSupportFragmentManager().beginTransaction().replace(R.id.fl_menu, menuFragment, "menuFragment").commit();
getSupportFragmentManager().beginTransaction().replace(R.id.fl_main, mainFragment, "mainFragment").commit();
需要展示的界面如下:
以上準(zhǔn)備工作完畢!
三、三種數(shù)據(jù)傳遞方式的相關(guān)操作
需求:我們點(diǎn)擊上面圖片中展示的對(duì)應(yīng)的條目數(shù)據(jù),讓右側(cè)(黃色按鈕)對(duì)應(yīng)的文本數(shù)據(jù)更換成條目展示的文本,例如:我點(diǎn)擊左側(cè)第4個(gè)條目,右側(cè)按鈕文本立馬更改成“這是第4條數(shù)據(jù)”,從而實(shí)現(xiàn)Fragment之間數(shù)據(jù)的傳遞。下面開(kāi)始介紹三種方法實(shí)現(xiàn)Fragment之間數(shù)據(jù)的傳遞。
方法一:
- 1、在MainFragment中設(shè)置一個(gè)setData()方法,在方法中設(shè)置更改按鈕名稱;
//MainFragment.java文件中
public void setData(String string) {
bt_main.setText(string);
}
- 2、在MenuFragment中的ListView條目點(diǎn)擊事件中通過(guò)標(biāo)簽獲取到MainFragment,并調(diào)用對(duì)應(yīng)的setData()方法,將數(shù)據(jù)設(shè)置進(jìn)去,從而達(dá)到數(shù)據(jù)傳遞的目的。
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
MainFragment mainFragment =
(MainFragment) getActivity()
.getSupportFragmentManager()
.findFragmentByTag("mainFragment");
mainFragment.setData(mDatas.get(position));
}
});
只需上面區(qū)區(qū)兩步即可達(dá)到數(shù)據(jù)傳遞的目的。
方法二:
采取接口回調(diào)的方式進(jìn)行數(shù)據(jù)傳遞。
- step1: 在Menuragment中創(chuàng)建一個(gè)接口以及接口對(duì)應(yīng)的set方法:
//MenuFragment.java文件中
public interface OnDataTransmissionListener {
public void dataTransmission(String data);
}
public void setOnDataTransmissionListener(OnDataTransmissionListener mListener) {
this.mListener = mListener;
}
- step2: 在MenuFragment中的ListView條目點(diǎn)擊事件中進(jìn)行接口進(jìn)行接口回調(diào)
//MenuFragment.java文件中
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
/**
* 方法二:采取接口回調(diào)的方式進(jìn)行數(shù)據(jù)傳遞
*/
if (mListener != null) {
mListener.dataTransmission(mDatas.get(position));
}
}
});
- step3: 在MainActivity中根據(jù)menuFragment獲取到接口的set方法,在這個(gè)方法中進(jìn)行進(jìn)行數(shù)據(jù)傳遞,具體如下:
//在MainActivity.java中
menuFragment.setOnDataTransmissionListener(new MenuFragment.OnDataTransmissionListener() {
@Override
public void dataTransmission(String data) {
mainFragment.setData(data); //注:對(duì)應(yīng)的mainFragment此時(shí)應(yīng)該要用final進(jìn)行修飾
}
});
通過(guò)上面的三步也可以輕松做到Fragment數(shù)據(jù)之間的傳遞。
方法三: 使用三方開(kāi)源框架:EventBus 那么問(wèn)題來(lái)了:EventBus是個(gè)啥東西??? 簡(jiǎn)單來(lái)說(shuō),EventBus是一款針對(duì)Android優(yōu)化的發(fā)布/訂閱(publish/subscribe)事件總線。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,線程之間傳遞消息。簡(jiǎn)化了應(yīng)用程序內(nèi)各組件間、組件與后臺(tái)線程間的通信。優(yōu)點(diǎn)是開(kāi)銷小,代碼更優(yōu)雅,以及將發(fā)送者和接收者解耦。比如請(qǐng)求網(wǎng)絡(luò),等網(wǎng)絡(luò)返回時(shí)通過(guò)Handler或Broadcast通知UI,兩個(gè)Fragment之間需要通過(guò)Listener通信,這些需求都可以通過(guò)EventBus實(shí)現(xiàn)。 下面我們就用EventBus來(lái)實(shí)現(xiàn)以下Fragment之間的數(shù)據(jù)傳遞:
- step1:引入EventBus
compile 'org.greenrobot:eventbus:3.0.0'
- step2:注冊(cè)事件接收者
這里MainFragment是要接收MenuFragment發(fā)送來(lái)的數(shù)據(jù),所以我們?cè)贛ainFragment中的onCreateView()方法中進(jìn)行注冊(cè):
EventBus.getDefault().register(this);
- step3:發(fā)送事件
注:發(fā)送事件之前其實(shí)還有一步定義事件類型,這里我們傳遞的數(shù)據(jù)只有一個(gè)類型,所以這一步取消了。
MenuFragment發(fā)送數(shù)據(jù)給MainFragment,所以我們?cè)贛enuFragment中將要傳遞的數(shù)據(jù)進(jìn)行發(fā)送事件操作:
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
EventBus.getDefault().post(mDatas.get(position));
}
});
- step4:接收消息并處理
在MainFragment中我們接收來(lái)自MenuFragment傳遞過(guò)來(lái)的數(shù)據(jù),并進(jìn)行對(duì)應(yīng)的處理(注:EventBus 3.0版本這一步必須要寫注解@Subscribe (與2.4版本有所區(qū)別)):
@Subscribe
public void onEvent(String data) {
bt_main.setText(data);
}
通過(guò)上面這一步即可完成數(shù)據(jù)之間的傳遞,需要注意的是在銷毀的時(shí)候我們要注銷事件接收。
- step5:注銷事件接收
//MainFragment.java中
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
以上五步完成了Fragment之間的數(shù)據(jù)傳遞,看似比上面兩個(gè)方法要復(fù)雜的多,但當(dāng)我們涉及到復(fù)雜的Fragment之間數(shù)據(jù)傳遞(例如Fragment中嵌套多層Fragment)時(shí),就會(huì)體會(huì)到EventBus的爽快之處~~~這里不進(jìn)行贅述了。
四、總結(jié)
對(duì)于以上三種方法,各自有各自的優(yōu)點(diǎn),我們可以根據(jù)實(shí)際需求采用對(duì)應(yīng)的方法;對(duì)于EventBus使用有不明白的地方,這里推薦一片博客供大家學(xué)習(xí)參考:http://gold.xitu.io/entry/570ae5668ac247004c3128a4
以上三個(gè)方法的講解源碼鏈接如下:
【源碼連接】https://github.com/Reign9201/datatransmission