相关文章:

1、《Fragment详解之一——概述》
2、《Fragment详解之二——基本使用方法》
3、《Fragment详解之三——管理Fragment(1)》
4、《Fragment详解之四——管理Fragment(2)》
5、《Fragment详解之五——Fragment间参数传递》
6、《Fragment详解之六——如何监听fragment中的回退事件与怎样保存fragment状态》

在关Fragment间参数的传递,有两种情况:

  • 第一种情况:同一个container中不同fragment间的参数传递。这种情况一般发生在fragment跳转时,上一个Fragment将参数传递给下一个Fragment。
  • 第二种情况:是同一个Activity中,不个container间Fragment的参数传递。

有关第一种情况,以前写过一篇文章,详细说明了上一个Fragment将参数传递给下一个Fragment,及数据回传的方法。详细参见: 《Fragment跳转时传递参数及结果回传的方法》

下面详细看看这两种参数传递方法。

一、同一个container间的参数传递。

有关这个问题,请大家移步以前写的一篇文章:《Fragment跳转时传递参数及结果回传的方法》,在这篇文章中有关Fragment跳转时的参数传递和结果回传已经讲的很清楚了,这里就没必要重新再写一遍,下面是这篇文章的效果图:

  • 1、在界面开始时,点击“加载第二个Fragment”按钮
  • 2、调起Fragment2,并向其传递一个参数“从Fragment1传来的参数”,显示在Fragment2中
  • 3、点击Fragment2中的四个小动物中的一个,会向Fragment1回传用户点击的是哪个动物,在Fragment1中显示出来。

看起来挺有意思?那就移步到这篇文章里看看吧

二、同一个Activity,不同container间的参数传递

这里到了这篇文章的重点内容了哦,这可并不是说上一部分不重要哈,其实上一部分要比这部分重要!同一个container中不同Fragment间的参数传递一般的工程都会用到的,所以大家一定要看。而我这里不讲,是因为以前有讲过,这里就没必要再重复一遍了,好了,废话说了好多……开整吧。
先看看效果图:
1、在这个Actiivty中有两个Fragment;
2、Fragment1中有一个listView,当我们点击ListView的Item的时候,把Item上的内容更新到Fragment2上

这里有多种实现方法,最可取的是方法三。我们由简到易慢慢讲。
我们想使两个fragment实例要能通信,那如果我们都能通过findViewById()找到所有的控件,直接操控的话,岂不就实现了。而通过findViewById()能找到所有控件实例的地方就是在Activity中了,所以这就有了方法一。

方法一:直接在Activity中操作

在Activity中找到对应的控件实例,然后直接操控即可。
先看看MainActivity的布局:activity_main.xml

[html] view plaincopy
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:id="@+id/main_layout"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="horizontal"
  6. android:baselineAligned="false" >
  7. <fragment
  8. android:id="@+id/fragment1"
  9. android:name="com.harvic.com.harvicblog5_1.Fragment1"
  10. android:layout_width="0dip"
  11. android:layout_height="match_parent"
  12. android:layout_weight="1" />
  13. <fragment
  14. android:id="@+id/fragment2"
  15. android:name="com.harvic.com.harvicblog5_1.Fragment2"
  16. android:layout_width="0dip"
  17. android:layout_height="match_parent"
  18. android:layout_weight="1" />
  19. </LinearLayout>

在这个布局中,横向放两个fragment,由于这里的fragment是静态添加的,所以每个fragment都是有id值的,所以这时候如果我们要获取某个fragment的实例,就可以通过FragmentManager::findFragmentById()来找到了。
然后是这两个fragment的布局。
fragment1.xml:

[html] view plaincopy
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent"
  4. android:background="#ff00ff"
  5. android:orientation="vertical" >
  6. <TextView
  7. android:layout_width="wrap_content"
  8. android:layout_height="wrap_content"
  9. android:text="This is fragment 1"
  10. android:textColor="#000000"
  11. android:textSize="25sp" />
  12. <ListView
  13. android:id="@+id/list"
  14. android:layout_width="match_parent"
  15. android:layout_height="match_parent"></ListView>
  16. </LinearLayout>

可以看到fragment1的布局中,除了一个标识当前Fragment的TextView,就是一个listview;
fragment2.xml:

[html] view plaincopy
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent"
  4. android:background="#ffff00"
  5. android:orientation="vertical" >
  6. <TextView
  7. android:id="@+id/fragment2_tv"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:text="This is fragment 2"
  11. android:textColor="#000000"
  12. android:textSize="25sp" />
  13. </LinearLayout>

可以看到在fragment2中非常干净,只有一个TextView来显示当前用户在fragment1中的点击结果。
下面看看在MainActivity中是如何实现的吧

[java] view plaincopy
  1. protected void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. setContentView(R.layout.activity_main);
  4. ArrayAdapter arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mStrings);
  5. ListView listView = (ListView)findViewById(R.id.list);
  6. listView.setAdapter(arrayAdapter);
  7. mFragment2_tv = (TextView)findViewById(R.id.fragment2_tv);
  8. listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  9. @Override
  10. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  11. mFragment2_tv.setText(mStrings[position]);
  12. }
  13. });
  14. }

其中:

[java] view plaincopy
  1. private String[] mStrings = {"Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
  2. "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",
  3. "Allgauer Emmentaler", "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
  4. "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",
  5. "Allgauer Emmentaler"};

难度不大,通过(ListView)findViewById(R.id.list);找到fragment1中的listview,通过(TextView)findViewById(R.id.fragment2_tv);找到fragment2中的textView,然后直接对他们进行操作。即下面的代码:

[java] view plaincopy
  1. listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  2. @Override
  3. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  4. mFragment2_tv.setText(mStrings[position]);
  5. }
  6. });

当用户点击listView的一个item时,将值setText到fragment2的textView中。

源码在文章底部给出

可见,直接在activity中操作各个fragment的控件就可以实现消息互传。但,这样真的好吗?如果每个fragment中的控件都在Activity中操作,那还要fragment干嘛!最最起码,应该每个fragment负责自己的控件操作才对嘛!
所以,我们对这种方法进行改进,将点击Item的赋值操作放到fragment1中去。所以,这就有方法二;

方法二:直接在fragment中操作

在这里我们会把所有方法写在Fragment1中,这里涉及到两方面的内容:
第一:在Fragment中如何获得自己控件的引用,比较这里Fragment1里的listview控件。
第二:在Fragment中如何获得其它Fragment页面中控件的引用,比如这里Fragment2里的TextView控件。
首先,获取自己控件引用的方法:
方法一:在onCreateView()中获取。
就比如这里获取自己的listView控件的引用,代码如下:

[java] view plaincopy
  1. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  2. Bundle savedInstanceState) {
  3. View rootView = inflater.inflate(R.layout.fragment1, container, false);
  4. listView = (ListView)rootView.findViewById(R.id.list);//获取自己视图里的控件引用,方法一
  5. return rootView;
  6. }

由于在onCreateView()中,还没有创建视图,所以在这里如果使用getView()方法将返回空。所以如果要获取其实图中指定控件的引用,只用用inflater.inflate()返回的rootView;在这个rootView()中用findViewById来查找。
方法二:在onActivityCreated()函数中获取。
从 《Fragment详解之一——概述》的流程图中可以看到,onActivityCreated()回调会在Activity的OnCreate()执行完成后再执行,也就是说,onActivityCreated()会在Activity的OnCreate()工作完成以后才会执行。所以当执行到onActivityCreated()的时候Activity已经创建完成,它其中的各个fragment也视图等等的也都已经创建完成。所在可以在这里获取跟Activity相关的各种资源。第二个问题中的获取其它Fragment页面中控件的引用也是在onActivityCreated()中来做的。先看看在onActivityCreated()中如何获得自己视图中控件的引用吧

[java] view plaincopy
  1. public void onActivityCreated(Bundle savedInstanceState) {
  2. super.onActivityCreated(savedInstanceState);
  3. listView = (ListView) getView().findViewById(R.id.list);//获取自己视图里的控件引用,方法二
  4. }

然后,获得其它Fragment页面中控件的引用的方法
在上面已经说了,要获取Activity中的资源,就必须等Acitivity创建完成以后,所以必须放在onActivityCreated()回调函数中。
其获取方法为:

[java] view plaincopy
  1. public void onActivityCreated(Bundle savedInstanceState) {
  2. super.onActivityCreated(savedInstanceState);
  3. mFragment2_tv = (TextView) getActivity().findViewById(R.id.fragment2_tv);//获取其它fragment中的控件引用的唯一方法!!!
  4. }

上面讲了一堆之后,下面就看看在Fragment1中如何实现的吧。
由上面的讲述可知,无论是获取自己视图中控件的引用还是获取其它fragment中控件的引用都可以放在onActivityCreated()函数中,所以我们就把它们全部放在onActivityCreated()中来实现了。

[java] view plaincopy
  1. public void onActivityCreated(Bundle savedInstanceState) {
  2. super.onActivityCreated(savedInstanceState);
  3. mFragment2_tv = (TextView) getActivity().findViewById(R.id.fragment2_tv);//获取其它fragment中的控件引用的唯一方法!!!
  4. listView = (ListView) getView().findViewById(R.id.list);//获取自己视图里的控件引用,方法二
  5. ArrayAdapter arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mStrings);
  6. listView.setAdapter(arrayAdapter);
  7. listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  8. @Override
  9. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  10. String str = mStrings[position];
  11. mFragment2_tv.setText(str);
  12. }
  13. });
  14. }

难度不大,也是获取到了每个控件以后,直接对他们进行操作。

源码在文章底部给出

我们这里直接在fragment1中操作了fragment2的控件,这样就违背了模块分离的思想,我们应该让他们各自处理各自的代码才好。所以,考虑到将他们分离,我们这里就出现了方法三。

方法三:在各自的fragment中操作

好,我们先想想要怎么解决这个问题,首先,我们把各自的事件放在各自的fragment中处理,即在fragment1中能得到当前用户点击的ITEM的String字符串,在fragment2中可以设置textview的值。那问题来了,各自获得了各自的东东,那通过什么让他们交互呢?
答案显然是activity。
很显然,在activity中可以直接通过FragmentManager::findFragmentById()来获取fragment2的实例。进而调用fragment2中的任意方法,这就实现了与fragment2的通信。
那fragment1又怎么把结果回传给Activity呢?大家如果在看到这里之前先看了《Fragment跳转时传递参数及结果回传的方法》就很容易想到,用回调!请记住。在不同页面中回传结果,回调是万能的解决方案。
1、Fragment2设置textView函数:
先看个简单的,fragment2中的处理代码:

[java] view plaincopy
  1. public class Fragment2 extends Fragment {
  2. private TextView mTv;
  3. …………
  4. public void setText(String text) {
  5. mTv.setText(text);
  6. }
  7. }

2、Fragment1中的处理方式:
(1)、定义接口及变量
由于是用回调,所以要先定义一个接口及对应的变量:

[java] view plaincopy
  1. private titleSelectInterface mSelectInterface;
  2. public interface titleSelectInterface{
  3. public void onTitleSelect(String title);
  4. }

(2)、接口变量赋值
接口是给activity用的,所以要在activity中给这里的接口变量赋值,可以有很多方法,当然可以选择写一个setXXX()函数来赋值,但如果用户忘了怎么办?所以我们要强制用户赋值。所以采用强转的方式,在fragment与activity相关联时,进行强转赋值:

[java] view plaincopy
  1. public void onAttach(Activity activity) {
  2. super.onAttach(activity);
  3. try {
  4. mSelectInterface = (titleSelectInterface) activity;
  5. } catch (Exception e) {
  6. throw new ClassCastException(activity.toString() + "must implement OnArticleSelectedListener");
  7. }
  8. }

采用强转的方式的问题在于,如果用户的activity没有implements titleSelectInterface,就会抛出错误,所以在调试过程中就会发现。
(3)、调用接口变量
下一步就是在fragment1中在用户点击listView的item的时候,将结果回传给Activity了,代码如下:

[java] view plaincopy
  1. public void onActivityCreated(Bundle savedInstanceState) {
  2. super.onActivityCreated(savedInstanceState);
  3. listView = (ListView) getView().findViewById(R.id.list);//获取自己视图里的控件引用,方法二
  4. ArrayAdapter arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mStrings);
  5. listView.setAdapter(arrayAdapter);
  6. listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  7. @Override
  8. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  9. String str = mStrings[position];
  10. mSelectInterface.onTitleSelect(str);
  11. }
  12. });
  13. }

(4)、在Activity中实现titleSelectInterface接口
首先是MainActivity必须实现titleSelectInterface接口,然后结果会在onTitleSelect(String title)中返回,在结果返回后利用fragment2.setText()操作textView;代码如下:

[java] view plaincopy
  1. public class MainActivity extends FragmentActivity implements Fragment1.titleSelectInterface {
  2. ……
  3. @Override
  4. public void onTitleSelect(String title) {
  5. FragmentManager manager = getSupportFragmentManager();
  6. Fragment2 fragment2 = (Fragment2)manager.findFragmentById(R.id.fragment2);
  7. fragment2.setText(title);
  8. }
  9. }

在上面代码中可以看出,在结果返回后,通过findFragmentById()来获得fragment2的实例,这里首次出现了findFragmentById()函数的用法,这个函数主要用来静态添加的fragment中,通过fragment的ID值来获取它的实例。在获得fragment2的实例以后,通过调用我们写好了setText()方法来将结果显示在textView中。

[java] view plaincopy
  1. Fragment2 fragment2 = (Fragment2)manager.findFragmentById(R.id.fragment2);

OK啦,到这里这篇文章就结束啦,源码过来啦。

参考文章:

1、《android Fragments详解五:与activity通讯》

2、《Inter-Fragment Communication》

Fragment详解之五——Fragment间参数传递相关推荐

  1. 【Android基础】Fragment 详解之Fragment介绍

    Fragment在Android 3.0( API 11)引入,是为了支持在大屏上显示更加动态.灵活的UI,比如在平板和电视上.Fragment可以看作是嵌套的Activity,类似ActivityG ...

  2. Fragment详解之四——管理Fragment(2)

    相关文章: 1.<Fragment详解之一--概述> 2.<Fragment详解之二--基本使用方法> 3.<Fragment详解之三--管理Fragment(1)> ...

  3. Fragment详解之二——基本使用方法

    前言:依然没有前言--文章写的太快,生活过得太有章程,前言都不知道写什么了-- 相关文章: 1.<Fragment详解之一--概述> 2.<Fragment详解之二--基本使用方法& ...

  4. Fragment详解之三——管理Fragment(1)

    前言:follow your heart,be your own king 相关文章: 1.<Fragment详解之一--概述> 2.<Fragment详解之二--基本使用方法> ...

  5. android fragment 优势,Android Fragment详解

    参考网址:Android Fragment详解 一.什么是Fragment? Fragment:是Android3.0开始新增的概念,意为碎片.Fragment是依赖于Activity的,不能独立存在 ...

  6. MTU和Fragment详解

    1. 基础知识 我们知道, 数据在网络上传输时, 要经过一段一段的链路.当数据从某一段链路的一端传到另一端的过程中, 需要考虑的是数据链路层协议, 在这一层, 我们观察到的数据包(PDU: Packe ...

  7. sh执行文件 参数传递_详解shell中脚本参数传递的两种方式

    方式一:$0,$1,$2.. 采用$0,$1,$2..等方式获取脚本命令行传入的参数,值得注意的是,$0获取到的是脚本路径以及脚本名,后面按顺序获取参数,当参数超过10个时(包括10个),需要使用${ ...

  8. Android面试收集录4 Fragment详解

    1.什么是Fragment? 你可以简单的理解为,Fragment是显示在Activity中的Activity. 它可以显示在Activity中,然后它也可以显示出一些内容. 因为它拥有自己的生命周期 ...

  9. Fragment详解

    一.Fragment简介    Fragment是Android3.0后引入的一个新的API,它出现的初衷是为了适应大屏幕的平板电脑, 当然现在它仍然是平板APP UI设计的宠儿,而且我们普通手机开发 ...

最新文章

  1. linux pytorch 快速安装
  2. 解决CentOS6.5虚拟机克隆后无法上网(网卡信息不一致)的问题
  3. CentOS 7环境安装Docker
  4. 经典算法题每日演练——第十题 树状数组
  5. 面试时,面试官到底在考察什么?
  6. Android 第十六课 使用LitePal查询数据
  7. jQuery使用ajax传输xml文档在IE中无法正确解析的问题
  8. python重复输入上面指令_stdin stdout python:如何重复使用同一输入文...
  9. LeetCode 1702. 修改后的最大二进制字符串(贪心)
  10. php strus2 漏洞攻击_关于对部分重要漏洞进行安全加固的预警通报
  11. Linux入门-安装篇(Debian 服务器版)
  12. TensorFlow实现卷积、反卷积和空洞卷积
  13. 基于JSP学生学籍管理系统
  14. 形容java工作者的句子_关于形容工作态度的句子
  15. 基于Unity3D的调用摄像头功能的实现
  16. 逻辑函数的两种标准形式
  17. C语言链表的删除代码实现
  18. Android通用流行框架大全,零基础入门学习android
  19. 计算机网络: IP地址,子网掩码,默认网关,DNS服务器详解
  20. 软件测试基础篇(1)

热门文章

  1. 【EventBus】发布-订阅模式 ( 使用代码实现发布-订阅模式 )
  2. 【Android 插件化】“ 插桩式 “ 插件化框架 ( 原理与实现思路 )
  3. 【Android 进程保活】提升进程优先级 ( 使用前台 Service 提高应用进程优先级 | 效果展示 | 源码资源 )
  4. Linux 下 top 命令的使用详解
  5. linux下部署svn服务器
  6. 作为面试官的一点小感想
  7. Xcache3.2.0不支持php7.0.11
  8. 安卓开发学习日记 DAY5——监听事件onClick的实现方法
  9. Xilinx ISE 14.7 安装教程
  10. c# list排序的三种实现方式 (转帖)