Fragment与Activity之间的通信

简介: 前言君子博学而日参省乎已,则知明而行无过矣。要显示Fragment,必须将Fragment添加到Activity中。添加到Activity中有如下两种方式。

前言

君子博学而日参省乎已,则知明而行无过矣。

要显示Fragment,必须将Fragment添加到Activity中。添加到Activity中有如下两种方式。
  • 在布局文件中使用<fragment../>元素添加Fragment,<fragment../>元素的android:name属性指定Fragment的实现类。
  • 在java代码中通过FragmentTransaction对象的add()方法来添加Fragment。
将Fragment添加到Activity之后,Fragment必须与Activity交互信息,这就需要Fragment能获取它所在的Activity,Activity也能获取它所包含的任意的Fragment。
  • Fragment获取它所在的Activtiy:调用Fragment的getActivity()方法即可返回它所在的Activity。

  • Activity获取它包含的Fragment:调用Activity关联的FragmentManager的findFragmentById(int id)或findFragmentByTag(String tag)方法即可获取指定的Fragment。

除此之外,Fragment与Activity可能还需要相互传递数据,可按如下方式进行。
  • Activity向Fragment传递数据:在Activity中创建Bundle数据包,并调用Fragment的setArguments(Bundle bundle)方法即可将Bundle数据包传给Fragment。

  • Fragment向Activity传递数据或Activity需要在Fragment运行中进行实时通信:在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity实现该回调接口,这样Fragment即可调用该回调方法将数据传给Activity。

代码示例

下面是一个显示图书详情的应用程序,将会在不同的手机屏幕下,显示出不同的效果,在小屏手机下,点击当前activity的列表项,将会跳转到另一个Activtiy,在平板上,列表将会在左边显示,内容将会在右边显示。
BookContent.java
public class BookContent {

    //定义一个内部类,作为系统的业务对象
    public static class Book
    {
        public Integer id;
        public String title;
        public String desc;
        public Book(Integer id, String title, String desc) {
            super();
            this.id = id;
            this.title = title;
            this.desc = desc;
        }
        @Override
        public String toString() {
            return title;
        }
    }

    //使用List集合记录系统所包含的Book对象
    public static List<Book> ITEMS = new ArrayList<Book>();
    //使用Map集合记录系统所包含的Book对象
    public static Map<Integer, Book> ITEM_MAP = new HashMap<Integer, Book>();

    static
    {
        //使用静态初始化代码。将Book对象添加到List集合、Map集合中
        addItem(new Book(1,"西游记","西游记是中国四大名著之一"));
        addItem(new Book(2,"水浒传","水浒传是中国四大名著之一"));
        addItem(new Book(3,"三国演义","三国演义是中国四大名著之一"));
        addItem(new Book(4,"红楼梦","红楼梦是中国四大名著之一"));
    }

    private static void addItem(Book book)
    {
        ITEMS.add(book);
        ITEM_MAP.put(book.id, book);
    }
}
activity_book_twopane.xml,平板端的内容布局
<?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="horizontal"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    android:divider="?android:attr/dividerHorizontal"
    android:showDividers="middle"
    >
    <!-- 添加一个Fragment -->
    <fragment
        android:name="com.zdf.fragmentdemo1.BookListFragment"
        android:id="@+id/book_list"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        />
    <!-- 添加一个FrameLayout -->
    <FrameLayout
        android:id="@+id/book_detail_container"
        android:layout_width="0dp"
        android:layout_weight="3"
        android:layout_height="match_parent"
        />
</LinearLayout>
activity_book_list.xml,小屏幕手机列表项的布局
<?xml version="1.0" encoding="utf-8"?>
<!-- 直接使用BookListFragment作为界面组件 -->
<fragment
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:name="com.zdf.fragmentdemo1.BookListFragment"
    android:id="@+id/book_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    />
/res/values-large/refs.xml 引用文件,根据屏幕大小使用不同的布局。
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 定义activity_book_list实际引用@layout/activity_book_twopane资源 -->
    <item type="layout" name="activity_book_list">@layout/activity_book_twopane</item>
</resources>
activity_book_detail.xml,小屏幕手机的第二个fragment的activity布局。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/book_detail_container1"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
fragment_book_detail.xml,小屏幕手机嵌入第二个Activity 的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
        style="?android:attr/textAppearanceLarge"
        android:id="@+id/book_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp"
        />
    <TextView
        style="?android:attr/textAppearanceMedium"
        android:id="@+id/book_desc"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp"
        />
</LinearLayout>
BookListActivity.java
public class BookListActivity extends Activity implements BookListFragment.Callbacks{


    //定义一个旗标,用于标识该应用是否支持大屏幕
    private boolean mTwoPane;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //指定加载R。layout。activtiy_book_list对应的界面布局
        //但实际上应用会根据屏幕分辨率加载不同的界面布局文件
        setContentView(R.layout.activity_book_list);
        //如果加载的界面布局文件包含ID为book_detail_container的组件
        if(findViewById(R.id.book_detail_container) != null)
        {
            mTwoPane = true;
            ((BookListFragment)getFragmentManager()
                    .findFragmentById(R.id.book_list))
                    .setActivateOnItemClick(true);
        }

    }

    @Override
    public void onItemSelected(Integer id) {
        if(mTwoPane)
        {
            //创建Bundle,准备向Fragment传入参数
            Bundle arguments = new Bundle();
            arguments.putInt(BookDetailFragment.ITEM_ID, id);
            //创建BookDetailFragment对象
            BookDetailFragment fragment = new BookDetailFragment();
            //向Fragment传入参数
            fragment.setArguments(arguments);
            //使用fragment替换book_detail_container容器当前显示的Fragment
            getFragmentManager().beginTransaction()
            .replace(R.id.book_detail_container, fragment).commit();
        }
        else
        {
            //创建启动BookDetailActivity的Intent
            Intent detailIntent = new Intent(this, BookDetailActivity.class);
            //设置传给BookDetailActivity的参数
            detailIntent.putExtra(BookDetailFragment.ITEM_ID, id);
            //启动Activity
            startActivity(detailIntent);
        }
    }
}
BookListFragment.java
public class BookListFragment extends ListFragment {

        private Callbacks mCallbacks;
        //该Fragment将通过该接口与它所在的Activity交互
        public interface Callbacks
        {
            public void onItemSelected(Integer id);
        }
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            //为该ListFragment设置Adapter
            setListAdapter(new ArrayAdapter<BookContent.Book>(getActivity(),
                    android.R.layout.simple_list_item_activated_1,
                    android.R.id.text1,BookContent.ITEMS));
        }

        //当该Fragment被添加、显示到Activity时,回调该方法。
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            //如果Activity没有实现Callbacks接口,抛出异常
            if(!(activity instanceof Callbacks))
            {
                throw new IllegalStateException("BookListFragment所在的Activity必须实现Callbacks接口");
            }
            //把该Activity当成Callbacks对象
            mCallbacks = (Callbacks) activity;
            Log.v("ATTACH", "1");
        }

        //当Fragment从它所属的Activtiy中被删除时回调该方法

        @Override
        public void onDetach() {
            super.onDetach();
            //将mCallbacks赋为null
            mCallbacks = null;
        }

        //当用户单击某列表项时激发该回调方法
        @Override
        public void onListItemClick(ListView l, View v, int position, long id) {
            super.onListItemClick(l, v, position, id);
            //激发mCallbacks的onItemSelected方法
            mCallbacks.onItemSelected(BookContent.ITEMS.get(position).id);
            Log.v("onListItemClick", "2");
        }

        public void setActivateOnItemClick(boolean activateOnItemClick)
        {
            getListView().setChoiceMode(activateOnItemClick ? ListView.CHOICE_MODE_SINGLE : ListView.CHOICE_MODE_NONE);
        }
}

BookDetailActivity.java
public class BookDetailActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //指定加载/res/layout目录下的activity_book_detail.xml布局文件
        //该界面布局文件内只定义了一个名为book_detail_container的FrameLayout
        setContentView(R.layout.activity_book_detail);
        //将ActionBar上的应用图标转换成可点击的按钮
        getActionBar().setDisplayHomeAsUpEnabled(true);

        if(savedInstanceState == null)
        {
            //创建BookDetailFragment对象
            BookDetailFragment fragment = new BookDetailFragment();
            //创建Bundle对象
            Bundle arguments = new Bundle();
            arguments.putInt(BookDetailFragment.ITEM_ID, getIntent().getIntExtra(BookDetailFragment.ITEM_ID, 0));
            //向Fragment传入参数
            fragment.setArguments(arguments);
            getFragmentManager().beginTransaction().add(R.id.book_detail_container1, fragment).commit();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        if(item.getItemId() == android.R.id.home)
        {
            //创建启动BookListActivity的Intent
            Intent intent = new Intent(this, BookListActivity.class);
            //添加额外的Flag,将Activity栈中处于FirstActivity之上的Activity弹出
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

}

BookDetailFragment.java
public class BookDetailFragment extends Fragment
{
    public static final String ITEM_ID = "item_id";
    //保存该Fragment显示的Book对象

    BookContent.Book book;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //如果启动该Fragment时包含ITEM_ID参数
        if(getArguments().containsKey(ITEM_ID))
        {
            book = BookContent.ITEM_MAP.get(getArguments().getInt(ITEM_ID));
        }
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.fragment_book_detail, container, false);
        if(book != null)
        {
            //让book_title文本框显示book对象的title属性
            ((TextView)rootView.findViewById(R.id.book_title)).setText(book.title);
            //让book_desc文本框显示book对象的desc属性
            ((TextView)rootView.findViewById(R.id.book_desc)).setText(book.desc);

        }
        return rootView;
    }
}

效果

小屏幕手机
img_955abfa946967a131529678c44ea3511.png
Screenshot_20171115-162550.png
点击列表时,跳转到另一个activity加载相应的fragment。
img_c0cab3605f6c411181ee4e7ba2abe26a.png
Screenshot_20171115-162715.png
大屏幕手机
img_d9a1be4bc9b3e600e979c4b258fba229.png
Screenshot_20171115-163704.png
目录
相关文章
|
5月前
|
人工智能 搜索推荐 API
API驱动电商个性化:用户行为分析接口
在电商领域,个性化体验至关重要。用户行为分析接口通过实时捕捉浏览、点击等行为,结合API技术实现个性化推荐与精准营销。本文详解其工作原理、实现方式及应用价值,助力电商平台提升用户体验与转化率。
161 0
|
Android开发
IDEA编译gradle提示This version of the Android Support plugin for IntelliJ IDEA (or Android Studio) cannot open this project, please retry with version 2020.3.1 or newer.
IDEA编译gradle提示This version of the Android Support plugin for IntelliJ IDEA (or Android Studio) cannot open this project, please retry with version 2020.3.1 or newer.
1402 1
|
9月前
|
存储 关系型数据库 MySQL
MySQL细节优化:关闭大小写敏感功能的方法。
通过这种方法,你就可以成功关闭 MySQL 的大小写敏感功能,让你的数据库操作更加便捷。
663 19
|
Android开发
Android面试题之Activity的启动模式和flag
Android Activity的四种启动模式:standard(默认,每次启动创建新实例),singleTop(栈顶复用,不走onCreate,调用onNewIntent),singleTask(栈内唯一,清除上方Activity)和singleInstance(单独栈内唯一)。启动模式在AndroidManifest.xml中配置,Intent Flags如FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_SINGLE_TOP可实现类似功能。了解这些对于处理Activity栈管理至关重要。
229 0
|
数据采集 JSON 数据可视化
PLC 西门子s7-200 轻松数据上云
​ 在在工业场景中,经常会使用到PLC进行各种设备的数据采集和控制。本教程介绍使用海创边缘网关配置s7-200 smart跑马灯场景效果,并实现数据上传海创物联网平台和阿里云物联网,实际项目中可能更多是跟MES相关系统进行对接,但技术逻辑相同,可参考!
7411 0
|
关系型数据库 MySQL Linux
Linux下查看软件安装与安装路径
Linux下查看软件安装与安装路径
1742 0
|
Android开发
40. 【Android教程】AsyncTask:异步任务
40. 【Android教程】AsyncTask:异步任务
395 2
|
Android开发
Android 自定义View 测量控件宽高、自定义viewgroup测量
Android 自定义View 测量控件宽高、自定义viewgroup测量
664 0
|
Java Android开发 开发者
Android Studio Profiler Memory (内存分析工具)的简单使用及问题分析
Android Studio Profiler Memory (内存分析工具)的简单使用及问题分析
3418 0
Android Studio Profiler Memory (内存分析工具)的简单使用及问题分析
|
设计模式 存储 前端开发
MVVM的优点和缺点
MVVM的优点和缺点
250 0