Fragment详解之五——Fragment间参数传递
相关文章:
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
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/main_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:baselineAligned="false" >
- <fragment
- android:id="@+id/fragment1"
- android:name="com.harvic.com.harvicblog5_1.Fragment1"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1" />
- <fragment
- android:id="@+id/fragment2"
- android:name="com.harvic.com.harvicblog5_1.Fragment2"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1" />
- </LinearLayout>
在这个布局中,横向放两个fragment,由于这里的fragment是静态添加的,所以每个fragment都是有id值的,所以这时候如果我们要获取某个fragment的实例,就可以通过FragmentManager::findFragmentById()来找到了。
然后是这两个fragment的布局。
fragment1.xml:
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#ff00ff"
- android:orientation="vertical" >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="This is fragment 1"
- android:textColor="#000000"
- android:textSize="25sp" />
- <ListView
- android:id="@+id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"></ListView>
- </LinearLayout>
可以看到fragment1的布局中,除了一个标识当前Fragment的TextView,就是一个listview;
fragment2.xml:
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#ffff00"
- android:orientation="vertical" >
- <TextView
- android:id="@+id/fragment2_tv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="This is fragment 2"
- android:textColor="#000000"
- android:textSize="25sp" />
- </LinearLayout>
可以看到在fragment2中非常干净,只有一个TextView来显示当前用户在fragment1中的点击结果。
下面看看在MainActivity中是如何实现的吧
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- ArrayAdapter arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mStrings);
- ListView listView = (ListView)findViewById(R.id.list);
- listView.setAdapter(arrayAdapter);
- mFragment2_tv = (TextView)findViewById(R.id.fragment2_tv);
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- mFragment2_tv.setText(mStrings[position]);
- }
- });
- }
其中:
- private String[] mStrings = {"Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
- "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",
- "Allgauer Emmentaler", "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
- "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",
- "Allgauer Emmentaler"};
难度不大,通过(ListView)findViewById(R.id.list);找到fragment1中的listview,通过(TextView)findViewById(R.id.fragment2_tv);找到fragment2中的textView,然后直接对他们进行操作。即下面的代码:
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- mFragment2_tv.setText(mStrings[position]);
- }
- });
当用户点击listView的一个item时,将值setText到fragment2的textView中。
可见,直接在activity中操作各个fragment的控件就可以实现消息互传。但,这样真的好吗?如果每个fragment中的控件都在Activity中操作,那还要fragment干嘛!最最起码,应该每个fragment负责自己的控件操作才对嘛!
所以,我们对这种方法进行改进,将点击Item的赋值操作放到fragment1中去。所以,这就有方法二;
方法二:直接在fragment中操作
在这里我们会把所有方法写在Fragment1中,这里涉及到两方面的内容:
第一:在Fragment中如何获得自己控件的引用,比较这里Fragment1里的listview控件。
第二:在Fragment中如何获得其它Fragment页面中控件的引用,比如这里Fragment2里的TextView控件。
首先,获取自己控件引用的方法:
方法一:在onCreateView()中获取。
就比如这里获取自己的listView控件的引用,代码如下:
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View rootView = inflater.inflate(R.layout.fragment1, container, false);
- listView = (ListView)rootView.findViewById(R.id.list);//获取自己视图里的控件引用,方法一
- return rootView;
- }
由于在onCreateView()中,还没有创建视图,所以在这里如果使用getView()方法将返回空。所以如果要获取其实图中指定控件的引用,只用用inflater.inflate()返回的rootView;在这个rootView()中用findViewById来查找。
方法二:在onActivityCreated()函数中获取。
从 《Fragment详解之一——概述》的流程图中可以看到,onActivityCreated()回调会在Activity的OnCreate()执行完成后再执行,也就是说,onActivityCreated()会在Activity的OnCreate()工作完成以后才会执行。所以当执行到onActivityCreated()的时候Activity已经创建完成,它其中的各个fragment也视图等等的也都已经创建完成。所在可以在这里获取跟Activity相关的各种资源。第二个问题中的获取其它Fragment页面中控件的引用也是在onActivityCreated()中来做的。先看看在onActivityCreated()中如何获得自己视图中控件的引用吧
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- listView = (ListView) getView().findViewById(R.id.list);//获取自己视图里的控件引用,方法二
- }
然后,获得其它Fragment页面中控件的引用的方法
在上面已经说了,要获取Activity中的资源,就必须等Acitivity创建完成以后,所以必须放在onActivityCreated()回调函数中。
其获取方法为:
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- mFragment2_tv = (TextView) getActivity().findViewById(R.id.fragment2_tv);//获取其它fragment中的控件引用的唯一方法!!!
- }
上面讲了一堆之后,下面就看看在Fragment1中如何实现的吧。
由上面的讲述可知,无论是获取自己视图中控件的引用还是获取其它fragment中控件的引用都可以放在onActivityCreated()函数中,所以我们就把它们全部放在onActivityCreated()中来实现了。
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- mFragment2_tv = (TextView) getActivity().findViewById(R.id.fragment2_tv);//获取其它fragment中的控件引用的唯一方法!!!
- listView = (ListView) getView().findViewById(R.id.list);//获取自己视图里的控件引用,方法二
- ArrayAdapter arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mStrings);
- listView.setAdapter(arrayAdapter);
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- String str = mStrings[position];
- mFragment2_tv.setText(str);
- }
- });
- }
难度不大,也是获取到了每个控件以后,直接对他们进行操作。
我们这里直接在fragment1中操作了fragment2的控件,这样就违背了模块分离的思想,我们应该让他们各自处理各自的代码才好。所以,考虑到将他们分离,我们这里就出现了方法三。
方法三:在各自的fragment中操作
好,我们先想想要怎么解决这个问题,首先,我们把各自的事件放在各自的fragment中处理,即在fragment1中能得到当前用户点击的ITEM的String字符串,在fragment2中可以设置textview的值。那问题来了,各自获得了各自的东东,那通过什么让他们交互呢?
答案显然是activity。
很显然,在activity中可以直接通过FragmentManager::findFragmentById()来获取fragment2的实例。进而调用fragment2中的任意方法,这就实现了与fragment2的通信。
那fragment1又怎么把结果回传给Activity呢?大家如果在看到这里之前先看了《Fragment跳转时传递参数及结果回传的方法》就很容易想到,用回调!请记住。在不同页面中回传结果,回调是万能的解决方案。
1、Fragment2设置textView函数:
先看个简单的,fragment2中的处理代码:
- public class Fragment2 extends Fragment {
- private TextView mTv;
- …………
- public void setText(String text) {
- mTv.setText(text);
- }
- }
2、Fragment1中的处理方式:
(1)、定义接口及变量
由于是用回调,所以要先定义一个接口及对应的变量:
- private titleSelectInterface mSelectInterface;
- public interface titleSelectInterface{
- public void onTitleSelect(String title);
- }
(2)、接口变量赋值
接口是给activity用的,所以要在activity中给这里的接口变量赋值,可以有很多方法,当然可以选择写一个setXXX()函数来赋值,但如果用户忘了怎么办?所以我们要强制用户赋值。所以采用强转的方式,在fragment与activity相关联时,进行强转赋值:
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- try {
- mSelectInterface = (titleSelectInterface) activity;
- } catch (Exception e) {
- throw new ClassCastException(activity.toString() + "must implement OnArticleSelectedListener");
- }
- }
采用强转的方式的问题在于,如果用户的activity没有implements titleSelectInterface,就会抛出错误,所以在调试过程中就会发现。
(3)、调用接口变量
下一步就是在fragment1中在用户点击listView的item的时候,将结果回传给Activity了,代码如下:
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- listView = (ListView) getView().findViewById(R.id.list);//获取自己视图里的控件引用,方法二
- ArrayAdapter arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mStrings);
- listView.setAdapter(arrayAdapter);
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- String str = mStrings[position];
- mSelectInterface.onTitleSelect(str);
- }
- });
- }
(4)、在Activity中实现titleSelectInterface接口
首先是MainActivity必须实现titleSelectInterface接口,然后结果会在onTitleSelect(String title)中返回,在结果返回后利用fragment2.setText()操作textView;代码如下:
- public class MainActivity extends FragmentActivity implements Fragment1.titleSelectInterface {
- ……
- @Override
- public void onTitleSelect(String title) {
- FragmentManager manager = getSupportFragmentManager();
- Fragment2 fragment2 = (Fragment2)manager.findFragmentById(R.id.fragment2);
- fragment2.setText(title);
- }
- }
在上面代码中可以看出,在结果返回后,通过findFragmentById()来获得fragment2的实例,这里首次出现了findFragmentById()函数的用法,这个函数主要用来静态添加的fragment中,通过fragment的ID值来获取它的实例。在获得fragment2的实例以后,通过调用我们写好了setText()方法来将结果显示在textView中。
- Fragment2 fragment2 = (Fragment2)manager.findFragmentById(R.id.fragment2);
OK啦,到这里这篇文章就结束啦,源码过来啦。
参考文章:
1、《android Fragments详解五:与activity通讯》
2、《Inter-Fragment Communication》
Fragment详解之五——Fragment间参数传递相关推荐
- 【Android基础】Fragment 详解之Fragment介绍
Fragment在Android 3.0( API 11)引入,是为了支持在大屏上显示更加动态.灵活的UI,比如在平板和电视上.Fragment可以看作是嵌套的Activity,类似ActivityG ...
- Fragment详解之四——管理Fragment(2)
相关文章: 1.<Fragment详解之一--概述> 2.<Fragment详解之二--基本使用方法> 3.<Fragment详解之三--管理Fragment(1)> ...
- Fragment详解之二——基本使用方法
前言:依然没有前言--文章写的太快,生活过得太有章程,前言都不知道写什么了-- 相关文章: 1.<Fragment详解之一--概述> 2.<Fragment详解之二--基本使用方法& ...
- Fragment详解之三——管理Fragment(1)
前言:follow your heart,be your own king 相关文章: 1.<Fragment详解之一--概述> 2.<Fragment详解之二--基本使用方法> ...
- android fragment 优势,Android Fragment详解
参考网址:Android Fragment详解 一.什么是Fragment? Fragment:是Android3.0开始新增的概念,意为碎片.Fragment是依赖于Activity的,不能独立存在 ...
- MTU和Fragment详解
1. 基础知识 我们知道, 数据在网络上传输时, 要经过一段一段的链路.当数据从某一段链路的一端传到另一端的过程中, 需要考虑的是数据链路层协议, 在这一层, 我们观察到的数据包(PDU: Packe ...
- sh执行文件 参数传递_详解shell中脚本参数传递的两种方式
方式一:$0,$1,$2.. 采用$0,$1,$2..等方式获取脚本命令行传入的参数,值得注意的是,$0获取到的是脚本路径以及脚本名,后面按顺序获取参数,当参数超过10个时(包括10个),需要使用${ ...
- Android面试收集录4 Fragment详解
1.什么是Fragment? 你可以简单的理解为,Fragment是显示在Activity中的Activity. 它可以显示在Activity中,然后它也可以显示出一些内容. 因为它拥有自己的生命周期 ...
- Fragment详解
一.Fragment简介 Fragment是Android3.0后引入的一个新的API,它出现的初衷是为了适应大屏幕的平板电脑, 当然现在它仍然是平板APP UI设计的宠儿,而且我们普通手机开发 ...
最新文章
- linux pytorch 快速安装
- 解决CentOS6.5虚拟机克隆后无法上网(网卡信息不一致)的问题
- CentOS 7环境安装Docker
- 经典算法题每日演练——第十题 树状数组
- 面试时,面试官到底在考察什么?
- Android 第十六课 使用LitePal查询数据
- jQuery使用ajax传输xml文档在IE中无法正确解析的问题
- python重复输入上面指令_stdin stdout python:如何重复使用同一输入文...
- LeetCode 1702. 修改后的最大二进制字符串(贪心)
- php strus2 漏洞攻击_关于对部分重要漏洞进行安全加固的预警通报
- Linux入门-安装篇(Debian 服务器版)
- TensorFlow实现卷积、反卷积和空洞卷积
- 基于JSP学生学籍管理系统
- 形容java工作者的句子_关于形容工作态度的句子
- 基于Unity3D的调用摄像头功能的实现
- 逻辑函数的两种标准形式
- C语言链表的删除代码实现
- Android通用流行框架大全,零基础入门学习android
- 计算机网络: IP地址,子网掩码,默认网关,DNS服务器详解
- 软件测试基础篇(1)
热门文章
- 【EventBus】发布-订阅模式 ( 使用代码实现发布-订阅模式 )
- 【Android 插件化】“ 插桩式 “ 插件化框架 ( 原理与实现思路 )
- 【Android 进程保活】提升进程优先级 ( 使用前台 Service 提高应用进程优先级 | 效果展示 | 源码资源 )
- Linux 下 top 命令的使用详解
- linux下部署svn服务器
- 作为面试官的一点小感想
- Xcache3.2.0不支持php7.0.11
- 安卓开发学习日记 DAY5——监听事件onClick的实现方法
- Xilinx ISE 14.7 安装教程
- c# list排序的三种实现方式 (转帖)