Android應(yīng)用開發(fā)中Fragment間通信的實(shí)現(xiàn)教程
為了重用Fragment UI 組件,在設(shè)計(jì)中你應(yīng)該通過定義每一個(gè)fragemnt自己的layout和行為,讓fragment的自包含和模塊化。一旦你定義了這些可重用的Fragment,你可以通過Activity將它們關(guān)聯(lián)起來并通過程序的邏輯代碼將他們連接起來以實(shí)現(xiàn)整體組合的UI。
你會(huì)經(jīng)常想要一個(gè)fragment與另一個(gè)fragment通信,例如基于用戶事件改變fragment中的內(nèi)容。所有fragment質(zhì)檢單額通信都是通過Activity關(guān)聯(lián)起來的。兩個(gè)fragment之間不應(yīng)該直接進(jìn)行通信。
定義接口
為了允許fragment和它的Activity通信,你應(yīng)該fragment類中定義一個(gè)接口并在Activity中實(shí)現(xiàn)它。Fragment在onAttach()回調(diào)函數(shù)中獲取接口的具體實(shí)現(xiàn)的對象。后面,fragment就可以調(diào)用接口中的方法實(shí)現(xiàn)與Activity的通信。
下面是一個(gè)Fragment一Activity通信的例子:
// 用來存放fragment的Activtiy必須實(shí)現(xiàn)這個(gè)接口 public interface OnHeadlineSelectedListener { public void onArticleSelected(int position); } @Override public void onAttach(Activity activity) { super.onAttach(activity); // 這是為了保證Activity容器實(shí)現(xiàn)了用以回調(diào)的接口。如果沒有,它會(huì)拋出一個(gè)異常。 try { mCallback = (OnHeadlineSelectedListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnHeadlineSelectedListener"); } }
現(xiàn)在fragment可以通過使用實(shí)現(xiàn)了OnHeadlineSelectedListener接口的mCallback實(shí)例調(diào)用onArticleSelected()方法(或其他在接口中的方法)將消息傳遞給Activity。
例如下面在fragment中的方法將會(huì)在用戶點(diǎn)擊一個(gè)List item的時(shí)候被調(diào)用。這個(gè)fragment使用回調(diào)接口將時(shí)間傳遞給父Activtity。
@Override public void onListItemClick(ListView l, View v, int position, long id) { // 發(fā)送時(shí)間給Activity宿主 mCallback.onArticleSelected(position); }
實(shí)現(xiàn)接口
為了接收從fragment傳遞過來的事件回調(diào),宿主Activity必須實(shí)現(xiàn)定義在fragment類中的接口。
例如,下面的activity實(shí)現(xiàn)了上個(gè)例子中的接口。
public static class MainActivity extends Activity implements HeadlinesFragment.OnHeadlineSelectedListener{ ... public void onArticleSelected(int position) { // 用戶選擇了HeadlinesFragment中的頭標(biāo)題后 // 做一些業(yè)務(wù)操作 } }
將消息傳遞給fragment
宿主Activity可以通過調(diào)用findFragmentById()方法獲取Fragment實(shí)例,然后直接調(diào)用Fragment的公有方法,將消息傳遞給Fragment。
例如,想象一下,之前講過的Activity可能包含有其他的fragment,而這些fragment通過上面的回調(diào)函數(shù)返回的接口動(dòng)態(tài)地顯示一些內(nèi)容。這種情況下,Activity可以將回調(diào)函數(shù)中接收到信息傳遞給需要的fragment。
public static class MainActivity extends Activity implements HeadlinesFragment.OnHeadlineSelectedListener{ ... public void onArticleSelected(int position) { // 用戶選中HeadlinesFragment中的頭標(biāo)題后 // 做一些必要的業(yè)務(wù)操作 ArticleFragment articleFrag = (ArticleFragment) getSupportFragmentManager().findFragmentById(R.id.article_fragment); if (articleFrag != null) { // 如果 article frag 不為空,那么我們在同時(shí)顯示兩個(gè)fragmnet的布局中... // 調(diào)用ArticleFragment中的方法去更新它的內(nèi)容 articleFrag.updateArticleView(position); } else { // 否則,我們就是在僅包含一個(gè)fragment的布局中并需要交換fragment... // 創(chuàng)建fragment并給他一個(gè)跟選中的文章有關(guān)的參數(shù) ArticleFragment newFragment = new ArticleFragment(); Bundle args = new Bundle(); args.putInt(ArticleFragment.ARG_POSITION, position); newFragment.setArguments(args); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); // 用這個(gè)fragment替換任何在fragment_container中的東西 // 并添加事務(wù)到back stack中以便用戶可以回退到之前的狀態(tài) transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); // 提交事務(wù) transaction.commit(); } } }
動(dòng)態(tài)加載的Fragment通信
fragment之間永遠(yuǎn)不能通信都是通過他們所依附的Activity來通信的,通過接口回調(diào)的方式來通信
Activity--->Fragment:在activity中創(chuàng)建Bundle數(shù)據(jù)包,并調(diào)用fragment的setArguments(Bundle bundle)方法
fragment--->Activity:在fragment類中定義一個(gè)接口,并在他所屬的activity中實(shí)現(xiàn)該接口,fragment在他的onAttach()方法執(zhí)行期間捕獲該接口的實(shí)現(xiàn),然后就可以調(diào)用該接口方法,以便跟activity通信。
下面的代碼實(shí)現(xiàn)了在一個(gè)Activity下有兩個(gè)Fragment,在一個(gè)Fragment中輸入值在另一個(gè)Fragment顯示
public class MainActivity extends Activity implements MyListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FragmentManager manager = getFragmentManager(); FragmentTransaction fragmentTransaction = manager.beginTransaction(); Fragment1 fragment1 = new Fragment1(); fragmentTransaction.add(R.id.layout1, fragment1); fragmentTransaction.commit(); } //在mainActivity中實(shí)現(xiàn)MyListener接口并實(shí)現(xiàn)它未實(shí)現(xiàn)的方法,在該方法中傳遞數(shù)據(jù) @Override public void send(String info) { Toast.makeText(this, "Activity成功接收" + info, 0).show(); Fragment2 fragment2 = new Fragment2(); Bundle bundle = new Bundle(); bundle.putString("name", info); fragment2.setArguments(bundle); FragmentManager manager = getFragmentManager(); FragmentTransaction fragmentTransaction = manager.beginTransaction(); //替換該Fragment fragmentTransaction.replace(R.id.layout2, fragment2, "fragment2"); fragmentTransaction.commit(); } }
上面的MainActivity布局就是添加兩個(gè)Linearlayout,下面是創(chuàng)建兩個(gè)Fragment,F(xiàn)ragment1的布局就是一個(gè)EditText一個(gè)Button,F(xiàn)ragment2的布局就是一個(gè)TextView。
public class Fragment1 extends Fragment { EditText et; Button enter; private String info; @Override public void onAttach(Activity activity) { listener = (MyListener) activity; super.onAttach(activity); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment1_lay,container, false); et = (EditText) view.findViewById(R.id.et); enter = (Button) view.findViewById(R.id.enter); enter.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { info = et.getText().toString(); listener.send(info); } }); return view; } public MyListener listener; //定義一個(gè)接口 public interface MyListener{ public void send(String info); } } public class Fragment2 extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment2_lay,container, false); TextView tv = (TextView) view.findViewById(R.id.tv); tv.setText(getArguments().get("name")+"");//獲取傳遞的值 Toast.makeText(getActivity(), "fragment"+getArguments().get("name")+"", 0).show(); return view; } }
靜態(tài)加載的fragment通信
fragment可以調(diào)用getActivity()方法獲取他所在的Activity
Activity可以調(diào)用FragmentManager的findFragmentById()或findFragmentByTag()方法獲取Fragment
如果是靜態(tài)加載的Fragmentn那么向Activity傳遞數(shù)據(jù)就很簡單了,在MainActivity的onCreate方法中:
FragmentManager fragmentManager = getFragmentManager(); Fragment fragment = fragmentManager.findFragmentById(R.id.frag);//靜態(tài)加載在Activity布局中設(shè)置的Fragment的ID MyFragment frag = (MyFragment) fragment; frag.setText1("fragment靜態(tài)傳值");
在Fragment類中設(shè)置它的get、set方法,
private String text1; public String getText1() { return text1; } public void setText1(String text1) { this.text1 = text1; }
下面直接調(diào)用就可以了:
String value = getText1();
- Android自定義ViewPagerIndicator實(shí)現(xiàn)炫酷導(dǎo)航欄指示器(ViewPager+Fragment)
- Android之Viewpager+Fragment實(shí)現(xiàn)懶加載示例
- Android 開發(fā)中fragment預(yù)加載問題
- Android開發(fā)技巧之Fragment的懶加載
- Android應(yīng)用開發(fā)中Fragment的靜態(tài)加載與動(dòng)態(tài)加載實(shí)例
- Android中使用開源框架eventbus3.0實(shí)現(xiàn)fragment之間的通信交互
- Android Fragment與Activity之間的相互通信實(shí)例代碼
- Android應(yīng)用開發(fā)中Fragment與Activity間通信示例講解
- Android中Fragment的加載方式與數(shù)據(jù)通信詳解
相關(guān)文章
Android實(shí)現(xiàn)按鈕點(diǎn)擊事件的三種方法總結(jié)
Button是程序用于和用戶進(jìn)行交互的一個(gè)重要控件。既然有Button,那肯定有onClick方法,下面就教大家三種實(shí)現(xiàn)點(diǎn)擊事件的方法,感興趣的可以了解一下2022-04-04使用Android實(shí)現(xiàn)一個(gè)懸浮在軟鍵盤上的輸入欄
app開發(fā)中經(jīng)常會(huì)遇到一些輸入框要懸浮到軟鍵盤上方的需求,下面這篇文章主要給大家介紹了關(guān)于如何使用Android實(shí)現(xiàn)一個(gè)懸浮在軟鍵盤上的輸入欄的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04Flutter 全局點(diǎn)擊空白處隱藏鍵盤實(shí)戰(zhàn)
這篇文章主要介紹了Flutter 全局點(diǎn)擊空白處隱藏鍵盤實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Android開發(fā)之手勢檢測及通過手勢實(shí)現(xiàn)翻頁功能的方法
這篇文章主要介紹了Android開發(fā)之手勢檢測及通過手勢實(shí)現(xiàn)翻頁功能的方法,結(jié)合實(shí)例形式分析了Android GestureDetector類實(shí)現(xiàn)手勢檢測功能的相關(guān)操作技巧,需要的朋友可以參考下2017-09-09Android中ListView下拉刷新的實(shí)現(xiàn)方法實(shí)例分析
這篇文章主要介紹了Android中ListView下拉刷新的實(shí)現(xiàn)方法,涉及Android操作ListView的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10Android 自定義密碼輸入框?qū)崿F(xiàn)代碼
最近做個(gè)項(xiàng)目自定義密碼輸入框功能,下面小編把實(shí)現(xiàn)思路分享到腳本之家平臺(tái),需要的朋友參考下吧2018-03-03AndroidManifest.xml <uses-feature>和<uses-permisstio
這篇文章主要介紹了AndroidManifest.xml <uses-feature>和<uses-permisstion>分析及比較的相關(guān)資料,需要的朋友可以參考下2017-06-06