【Android】Fragment与Activity通信

多个Fragment组件可以拼接成一个Activity,那么这些Fragment如何通信呢?例如,一个显示新闻的Activity有两个Fragment,一个显示标题列表,一个显示新闻内容,点击标题列表项的时候就去更新新闻内容。为了实现Fragment的重用,Fragment之间不应该直接通信,而应该通过Activity通信。由于Fragment并不知道自己会寄生在哪个Activity,所以Fragment不知道如何向宿主Activity发送消息。那么Fragment如何与Activity通信呢?虽然Fragment不知道自己会寄生在哪个Activity下,但是Activity知道寄生在它内部的Fragment,所以可以让Activity实现一个Fragment能够识别的接口。Fragment通过接口回调,即可向其他Fragment发送消息。

下面通过一个例子展示Fragment如何与Activity通信。

新闻列表Fragment:

[java] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. package com.zzj.ui.activityTalkWithFragmentDemo;  
  2.   
  3. import android.app.Activity;  
  4. import android.app.ListFragment;  
  5. import android.os.Bundle;  
  6. import android.view.View;  
  7. import android.widget.ArrayAdapter;  
  8. import android.widget.ListView;  
  9.   
  10. public class TitleListFragment extends ListFragment {  
  11.   
  12.     public interface TitleClick {  
  13.         public void onClick(int titleIndex);  
  14.     }  
  15.   
  16.     private TitleClick titleClick;  
  17.   
  18.     @Override  
  19.     public void onAttach(Activity activity) {  
  20.         super.onAttach(activity);  
  21.   
  22.         if (activity instanceof TitleClick) {  
  23.             titleClick = (TitleClick) activity;  
  24.         } else {  
  25.             throw new RuntimeException(  
  26.                     "TitleListFragment所在的Activity必须实现TitleClick接口!");  
  27.         }  
  28.     }  
  29.   
  30.     @Override  
  31.     public void onActivityCreated(Bundle savedInstanceState) {  
  32.         super.onActivityCreated(savedInstanceState);  
  33.         Bundle bundle = getArguments();  
  34.         String[] titles = bundle.getStringArray("titles");  
  35.         setListAdapter(new ArrayAdapter<String>(getActivity(),  
  36.                 android.R.layout.simple_list_item_1, titles));  
  37.     }  
  38.   
  39.     @Override  
  40.     public void onListItemClick(ListView l, View v, int position, long id) {  
  41.         titleClick.onClick(position);  
  42.     }  
  43.   
  44.     @Override  
  45.     public void onDetach() {  
  46.         super.onDetach();  
  47.         titleClick = null;  
  48.     }  
  49.   
  50. }  

该Fragment无需布局文件。

 

新闻内容Fragment:

[java] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. package com.zzj.ui.activityTalkWithFragmentDemo;  
  2.   
  3. import android.app.Fragment;  
  4. import android.os.Bundle;  
  5. import android.view.LayoutInflater;  
  6. import android.view.View;  
  7. import android.view.ViewGroup;  
  8. import android.widget.TextView;  
  9.   
  10. import com.zzj.ui.R;  
  11.   
  12. public class ContentFragment extends Fragment {  
  13.     private TextView contentView;  
  14.   
  15.     @Override  
  16.     public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  17.             Bundle savedInstanceState) {  
  18.         View view = inflater.inflate(R.layout.news_fragment_content, container,  
  19.                 false);  
  20.         return view;  
  21.     }  
  22.   
  23.     @Override  
  24.     public void onActivityCreated(Bundle savedInstanceState) {  
  25.         super.onActivityCreated(savedInstanceState);  
  26.         contentView = (TextView) getActivity().findViewById(  
  27.                 R.id.textView_content);  
  28.         updateContent(getArguments().getString("content"));  
  29.     }  
  30.   
  31.     /** 
  32.      * 更新内容 
  33.      *  
  34.      * @param content 
  35.      */  
  36.     public void updateContent(String contentText) {  
  37.         contentView.setText(contentText);  
  38.     }  
  39. }  

新闻内容Fragment布局文件:

[html] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:id="@+id/textView_content"  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.         android:autoLink="web" />  
  12.   
  13. </LinearLayout>  

 

 

下面的Activity组装了上面的两个Fragment,并且实现TitleListFragment.TitleClick接口:

[java] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. package com.zzj.ui.activityTalkWithFragmentDemo;  
  2.   
  3. import android.app.Activity;  
  4. import android.app.FragmentTransaction;  
  5. import android.os.Bundle;  
  6.   
  7. import com.zzj.ui.R;  
  8. import com.zzj.ui.activityTalkWithFragmentDemo.TitleListFragment.TitleClick;  
  9.   
  10. public class ActivityTWFragment extends Activity implements TitleClick {  
  11.   
  12.     TitleListFragment titleList;  
  13.     ContentFragment content;  
  14.     String[] titles = new String[] { "阿里上市", "百度直达号", "腾讯企业号" };  
  15.     String[] contents = new String[] { "http://www.alibaba.com",  
  16.             "http://www.baidu.com", "http://www.qq.com" };  
  17.   
  18.     @Override  
  19.     protected void onCreate(Bundle savedInstanceState) {  
  20.         super.onCreate(savedInstanceState);  
  21.         setContentView(R.layout.activity_talkwith_fragment);  
  22.   
  23.         FragmentTransaction transaction = getFragmentManager()  
  24.                 .beginTransaction();  
  25.   
  26.         titleList = (TitleListFragment) getFragmentManager().findFragmentByTag(  
  27.                 "title");  
  28.         if (titleList == null) {  
  29.             titleList = new TitleListFragment();  
  30.             Bundle bundle = new Bundle();  
  31.             bundle.putStringArray("titles", titles);  
  32.             // This can only be called before the fragment has been attached to  
  33.             // its activity  
  34.             titleList.setArguments(bundle);  
  35.             transaction.add(R.id.title_list, titleList, "title");  
  36.         }  
  37.         content = (ContentFragment) getFragmentManager().findFragmentByTag(  
  38.                 "content");  
  39.         if (content == null) {  
  40.             content = new ContentFragment();  
  41.             // 初始化显示第一条内容  
  42.             Bundle args = new Bundle();  
  43.             args.putString("content", "http://www.alibaba.com");  
  44.             content.setArguments(args);  
  45.             transaction.add(R.id.content, content, "content");  
  46.         }  
  47.         transaction.commit();  
  48.     }  
  49.   
  50.     @Override  
  51.     public void onClick(int titleIndex) {  
  52.         content.updateContent(contents[titleIndex]);  
  53.     }  
  54. }  

Activity布局文件:

[html] view plain copy
 
 print?在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:baselineAligned="false"  
  6.     android:orientation="horizontal" >  
  7.   
  8.     <FrameLayout  
  9.         android:id="@+id/title_list"  
  10.         android:layout_width="0dp"  
  11.         android:layout_height="match_parent"  
  12.         android:layout_weight="1" >  
  13.     </FrameLayout>  
  14.   
  15.     <FrameLayout  
  16.         android:id="@+id/content"  
  17.         android:layout_width="0dp"  
  18.         android:layout_height="match_parent"  
  19.         android:layout_weight="2" >  
  20.     </FrameLayout>  
  21.   
  22. </LinearLayout>  

效果:

 

 

温馨提示:

1.可以在Fragment中定义一些业务方法,以更好地实现重用。例子中显示新闻内容的Fragment定义了一个更新内容的方法,这样就不必在Activity中去查找显示新闻内容的TextView组件。

2.如果要向Fragment传递参数,可以调用Fragment的setArguments(Bundle args)方法,该方法必须在调用onAttach(Activity activity)方法之前调用。

posted @ 2016-11-28 16:04  天涯海角路  阅读(114)  评论(0)    收藏  举报