一直想總結一下Fragment與Fragment、Activity通信的問題,今天有時間一共總結了三種,權當抛磚引玉,如果大家還有更好的方式來實作Fragment和Fragment、Activity的通信,歡迎提出來,我們一起學習。好了,我們先來看看今天要實作的一個效果圖:
左邊是一個Fragment,右邊是一個Fragment,當我們點選左邊的Fragment的時候,右邊的Fragment中顯示出我們所點選的人的作品,我們就來看看怎樣實作兩個Fragment之間的通信。
1.直接在一個Fragment中調用另外一個Fragment中的方法
我們可以直接在一個Fragment中調用另外一個Fragment的公開方法,前提是要先拿到另外一個Fragment的執行個體,我們先來看看怎樣在左邊的Fragment中拿到右邊Fragment的執行個體:
ContentFragment cf = (ContentFragment) getActivity()
.getFragmentManager().findFragmentById(
R.id.content_fg);
cf.showPro(name);
我們通過宿主Activity拿到FragmentManager,進而再拿到右邊的Fragment,然後調用右邊Fragment裡邊的showPro方法,其中要傳入的參數是左邊點選的人名,我們看看右邊Fragment中的showPro方法:
public void showPro(String key) {
list = map.get(key);
adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, list);
lv.setAdapter(adapter);
}
先根據傳進來的人名拿到該人作品的資料集,然後構造一個adapter指派給listview,很簡單吧。使用這種方式我們可以直接在一個Fragment中調用另一個Fragment的公開方法,進而實作兩個Fragment的通信。
這種方法适于那些我們在布局檔案中就已經定義了的Fragment,這種Fragment每個都有id,可以通過FragmentManager找到,但是如果我們使用了ViewPager,即每個Fragment都是動态添加進來的,這個時候我們無法通過FragmentManager獲得另外一個Fragment的執行個體,那麼該怎麼辦呢?這時我們就要用到下面這種方式了。
2.使用接口
接口可以實作兩個Fragment之間的通信,也可以實作Fragment和Activity之間的通信,這大概是用的比較多的一種方式,也是個人比較推薦的一種方式,使用接口來實作兩個Fragment之間通信,要通過宿主Activity中轉一下,如果是Fragment和宿主Activity通信則直接調用即可,我們先看看上圖中點選韓愈的時候怎麼出現他的作品。首先在左邊的Fragment中定義一個接口:
public interface showPro {
public void showProByName(String name);
}
然後定義一個接口變量:
private showPro mCallback;
我們要在宿主Activity中實作這個接口,這樣當Fragment調用onAttach方法時我們就可以執行個體化這個接口了:
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity != null) {
mCallback = (showPro) activity;
}
}
當mCallback執行個體化之後,那麼我們在點選韓愈的時候就可以調用這裡邊的showProByName方法了:
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
TextView nameTV = (TextView) view;
String name = nameTV.getText().toString();
if ("韓愈".equals(name)) {
mCallback.showProByName(name);
}
}
});
當然,這個方法的具體實作在宿主Activity中,當宿主Activity實作了showPro接口之後,接着就要實作它裡邊的方法了:
public class MainActivity extends Activity implements showPro {
private ContentFragment cf;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getActionBar().hide();
cf = (ContentFragment) getFragmentManager().findFragmentById(
R.id.content_fg);
}
@Override
public void showProByName(String name) {
cf.showPro(name);
}
}
我們在接口的方法中調用右邊Fragment中的showPro方法,并将目前人名作為參數傳入,這個方法與1中相同,我就不貼代碼了。這個方法與1中介紹的方法相比,雖然有點麻煩,但是可以有效的解決在一個Fragment中拿不到另一個Fragment執行個體的問題,具體應用場景就是ViewPager中的Fragment之間通信。
3.使用廣播
不論我們有沒有用ViewPager,都可以用廣播實作兩個Fragment之間的通信,廣播算是這裡最靈活的通信方式了,我們看看在左邊Fragment中發送廣播:
Intent intent = new Intent("showPro");
intent.putExtra("name", name);
LocalBroadcastManager.getInstance(getActivity())
.sendBroadcast(intent);
在右邊Fragment中接收廣播:
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager
.getInstance(getActivity());
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("showPro");
BroadcastReceiver br = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String key = intent.getStringExtra("name");
list = map.get(key);
adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, list);
lv.setAdapter(adapter);
}
};
localBroadcastManager.registerReceiver(br, intentFilter);
這些都是廣播基本的使用方法,我就不啰嗦了。
個人覺得,雖然廣播用起來最友善,但是在選擇使用哪種通信方式的時候,優先選擇上面兩種,如果前兩種方式都不可以,再考慮使用廣播。
續:
之前還忽略了一種,這裡補充一下。
4.Fragment直接調用Activity中的public方法
我們也可以直接在Fragment中調用Activity中的公開方法,如下:
((MainActivity) getActivity()).showProByName(name);
這裡的showProByName就是我們上文貼出來的那個MainActivity中的方法。
如果大家還有更好的實作兩個Fragment通信的方式,歡迎提出來,一起學習。
本文Demo下載下傳https://github.com/lenve/fragmentMsg