【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:
- package com.zzj.ui.activityTalkWithFragmentDemo;
- import android.app.Activity;
- import android.app.ListFragment;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.ArrayAdapter;
- import android.widget.ListView;
- public class TitleListFragment extends ListFragment {
- public interface TitleClick {
- public void onClick(int titleIndex);
- }
- private TitleClick titleClick;
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- if (activity instanceof TitleClick) {
- titleClick = (TitleClick) activity;
- } else {
- throw new RuntimeException(
- "TitleListFragment所在的Activity必须实现TitleClick接口!");
- }
- }
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- Bundle bundle = getArguments();
- String[] titles = bundle.getStringArray("titles");
- setListAdapter(new ArrayAdapter<String>(getActivity(),
- android.R.layout.simple_list_item_1, titles));
- }
- @Override
- public void onListItemClick(ListView l, View v, int position, long id) {
- titleClick.onClick(position);
- }
- @Override
- public void onDetach() {
- super.onDetach();
- titleClick = null;
- }
- }
该Fragment无需布局文件。
新闻内容Fragment:
- package com.zzj.ui.activityTalkWithFragmentDemo;
- import android.app.Fragment;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.TextView;
- import com.zzj.ui.R;
- public class ContentFragment extends Fragment {
- private TextView contentView;
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.news_fragment_content, container,
- false);
- return view;
- }
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- contentView = (TextView) getActivity().findViewById(
- R.id.textView_content);
- updateContent(getArguments().getString("content"));
- }
- /**
- * 更新内容
- *
- * @param content
- */
- public void updateContent(String contentText) {
- contentView.setText(contentText);
- }
- }
新闻内容Fragment布局文件:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <TextView
- android:id="@+id/textView_content"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:autoLink="web" />
- </LinearLayout>
下面的Activity组装了上面的两个Fragment,并且实现TitleListFragment.TitleClick接口:
- package com.zzj.ui.activityTalkWithFragmentDemo;
- import android.app.Activity;
- import android.app.FragmentTransaction;
- import android.os.Bundle;
- import com.zzj.ui.R;
- import com.zzj.ui.activityTalkWithFragmentDemo.TitleListFragment.TitleClick;
- public class ActivityTWFragment extends Activity implements TitleClick {
- TitleListFragment titleList;
- ContentFragment content;
- String[] titles = new String[] { "阿里上市", "百度直达号", "腾讯企业号" };
- String[] contents = new String[] { "http://www.alibaba.com",
- "http://www.baidu.com", "http://www.qq.com" };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_talkwith_fragment);
- FragmentTransaction transaction = getFragmentManager()
- .beginTransaction();
- titleList = (TitleListFragment) getFragmentManager().findFragmentByTag(
- "title");
- if (titleList == null) {
- titleList = new TitleListFragment();
- Bundle bundle = new Bundle();
- bundle.putStringArray("titles", titles);
- // This can only be called before the fragment has been attached to
- // its activity
- titleList.setArguments(bundle);
- transaction.add(R.id.title_list, titleList, "title");
- }
- content = (ContentFragment) getFragmentManager().findFragmentByTag(
- "content");
- if (content == null) {
- content = new ContentFragment();
- // 初始化显示第一条内容
- Bundle args = new Bundle();
- args.putString("content", "http://www.alibaba.com");
- content.setArguments(args);
- transaction.add(R.id.content, content, "content");
- }
- transaction.commit();
- }
- @Override
- public void onClick(int titleIndex) {
- content.updateContent(contents[titleIndex]);
- }
- }
Activity布局文件:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:baselineAligned="false"
- android:orientation="horizontal" >
- <FrameLayout
- android:id="@+id/title_list"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1" >
- </FrameLayout>
- <FrameLayout
- android:id="@+id/content"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="2" >
- </FrameLayout>
- </LinearLayout>
效果:
温馨提示:
1.可以在Fragment中定义一些业务方法,以更好地实现重用。例子中显示新闻内容的Fragment定义了一个更新内容的方法,这样就不必在Activity中去查找显示新闻内容的TextView组件。
2.如果要向Fragment传递参数,可以调用Fragment的setArguments(Bundle args)方法,该方法必须在调用onAttach(Activity activity)方法之前调用。

浙公网安备 33010602011771号