Android - fragment Manager
fragment基本使用:
http://www.cnblogs.com/qlky/p/5415679.html
Fragmeng优点
- Fragment可以使你能够将activity分离成多个可重用的组件,每个都有它自己的生命周期和UI。
- Fragment可以轻松得创建动态灵活的UI设计,可以适应于不同的屏幕尺寸。从手机到平板电脑。
- Fragment是一个独立的模块,紧紧地与activity绑定在一起。可以运行中动态地移除、加入、交换等。
- Fragment提供一个新的方式让你在不同的安卓设备上统一你的UI。
- Fragment 解决Activity间的切换不流畅,轻量切换。
- Fragment 替代TabActivity做导航,性能更好。
- Fragment 在4.2.版本中新增嵌套fragmeng使用方法,能够生成更好的界面效果。
- Fragment做局部内容更新更方便,原来为了到达这一点要把多个布局放到一个activity里面,现在可以用多Fragment来代替,只有在需要的时候才加载Fragment,提高性能
生命周期
1、FragmentManager
要管理activity中的fragments,你就需要使用FragmentManager。通过getFragmentManager()或getSupportFragmentManager()获得
常用的方法有:
- manager.findFragmentById(); //根据ID来找到对应的Fragment实例,主要用在静态添加fragment的布局中,因为静态添加的fragment才会有ID
- manager.findFragmentByTag();//根据TAG找到对应的Fragment实例,主要用于在动态添加的fragment中,根据TAG来找到fragment实例
- manager.getFragments();//获取所有被ADD进Activity中的Fragment
2、FragmentTransaction
一般用来对当前的Fragment进行管理,包括add,replace,remove;
常用的针对Fragment的方法有:
- //将一个fragment实例添加到Activity的最上层
- add(int containerViewId, Fragment fragment, String tag);
- //将一个fragment实例从Activity的fragment队列中删除
- remove(Fragment fragment);
- //替换containerViewId中的fragment实例,注意,它首先把containerViewId中所有fragment删除,然后再add进去当前的fragment
- replace(int containerViewId, Fragment fragment);
三、有关回滚——FragmentTransaction
1、FragmentTransaction事务回滚使用方法:
上部分,我们讲了有关添加、删除Fragment的操作,想将上一次commit的操作返回时,要怎么做呢。这就需要FragmentTransaction的回滚功能了。
要使用回滚功能,只需要要使用下面两个代码:
在transaction.commit()之前,使用addToBackStack()将其添加到回退栈中。
transaction.addToBackStack(String tag);
在需要回退时,使用popBackStack()将最上层的操作弹出回退栈。
manager.popBackStack();
这里的popBackStack()是弹出默认的最上层的栈顶内容。
当栈中有多层时,我们可以根据id或TAG标识来指定弹出到的操作所在层。函数如下:
- void popBackStack(int id, int flags);
- void popBackStack(String name, int flags);
其中
- 参数int id是当提交变更时transaction.commit()的返回值。
- 参数string name是transaction.addToBackStack(String tag)中的tag值;
- 至于int flags有两个取值:0或FragmentManager.POP_BACK_STACK_INCLUSIVE;
- 当取值0时,表示除了参数一指定这一层之上的所有层都退出栈,指定的这一层为栈顶层;
- 当取值POP_BACK_STACK_INCLUSIVE时,表示连着参数一指定的这一层一起退出栈;
- 除了这几个函数,还有下面几个函数:有关他们的使用,我们在这小部分结尾时会提到
- popBackStackImmediate()
- popBackStackImmediate(String tag)
- popBackStackImmediate(String tag, int flag)
- popBackStackImmediate(int id, int flag)
2、回退栈(back stack)状态改变监听
FragmentManager还为我们提供了监控回退栈状态改变的方法:
- FragmentManager::addOnBackStackChangedListener(listener);//添加监听器
- FragmentManager::removeOnBackStackChangedListener(listener);//移除监听器
通过添加监听器,就可以在回退栈内容改变时,及时收到通知;
3、Transaction事务回退的原则
这里我们着重讲一下,回退是以commit()提交的一次事务为单位的,而不是以其中的add,replace等等操作为单位回退的,即,如果我们在一次提交是添加了fragment2,fragment3,fragment4,那么回退时,会依据添加时的顺序,将它们一个个删除,返回到没有添加fragment4,fragment3,fragment2的状态。
一、hide()、show()
1、基本使用
这两个函数的功能非常简单,
- public FragmentTransaction hide(Fragment fragment);//将指定的fragment隐藏不显示
- public FragmentTransaction show(Fragment fragment);//将以前hide()过的fragment显示出来
2、在实战中的运用方法
如果我们使用replace来切换页面,那么在每次切换的时候,Fragment都会重新实例化,重新加载一边数据,这样非常消耗性能和用户的数据流量。
这是因为replace操作,每次都会把Container中的现有的fragment实例清空,然后再把指定的fragment添加进去,就就造成了在切换到以前的fragment时,就会重新实例会fragment。
正确的切换方式是add(),切换时hide(),add()另一个Fragment;再次切换时,只需hide()当前,show()另一个。
这样就能做到多个Fragment切换不重新实例化:(基本算法如下)
public void switchContent(Fragment from, Fragment to) {
if (!to.isAdded()) { // 先判断是否被add过
transaction.hide(from).add(R.id.content_frame, to).commit(); // 隐藏当前的fragment,add下一个到Activity中
} else {
transaction.hide(from).show(to).commit(); // 隐藏当前的fragment,显示下一个
}
}
大家可能觉得这里有个问题,如果我们要show()的fragment不在最顶层怎么办?如果不在ADD队列的队首,那显然show()之后是不可见的;那岂不影响了APP逻辑。大家有这个想法是很棒的,但在APP中不存在这样的情况,因为我们的APP的fragment是一层层ADD进去的,而且我们的fragment实例都是唯一的,用TAG来标识,当退出的时候也是一层层剥离的,所以当用户的动作导致要添加某个fragment时,那说明这个fragment肯定是在栈顶的。
二、detach()、attach()
这两个函数的声明如下:
- public FragmentTransaction detach(Fragment fragment);
- public abstract FragmentTransaction attach(Fragment fragment);
detach():会将view与fragment分离,将此将view从viewtree中删除!而且将fragment从Activity的ADD队列中移除!所以在使用detach()后,使用fragment::isAdded()返回的值是false;但此fragment实例并不会删除,此fragment的状态依然保持着使用,所以在fragmentManager中仍然可以找到,即通过FragmentManager::findViewByTag()仍然是会有值的。
attach():显然这个方法与detach()所做的工作相反,它一方面利用fragment的onCreateView()来重建视图,一方面将此fragment添加到ADD队列中;这里最值得注意的地方在这里:由于是将fragment添加到ADD队列,所以只能添加到列队头部,所以attach()操作的结果是,最新操作的页面始终显示在最前面!这也就解释了下面的例子中,为了fragment2 detach()后,当再次attach()后,却跑到了fragment3的前面的原因。还有,由于这里会将fragment添加到Activity的ADD队列中,所以在这里调用fragment::isAdded()将返回True;
三、Fragment参数传递
在关Fragment间参数的传递,有两种情况:
- 第一种情况:同一个container中不同fragment间的参数传递。这种情况一般发生在fragment跳转时,上一个Fragment将参数传递给下一个Fragment。
- 第二种情况:是同一个Activity中,不个container间Fragment的参数传递。
有关第一种情况,以前写过一篇文章,详细说明了上一个Fragment将参数传递给下一个Fragment,及数据回传的方法。详细参见:《Fragment跳转时传递参数及结果回传的方法》
当我们实例化自定义Fragment时,官方推荐Fragment.setArguments(Bundle bundle)这种方式来传递参数,而不推荐通过构造方法直接来传递参数
在屏幕旋转时,activity会重构,而依附在activity上的fragment最终会通过反射无参构造实例化一个新的Fragment,并且给mArgments初始化为原先的值,而原来的Fragment实例的数据都丢失了,并重新进行了初始化
通过上面的分析,我们可以知道Activity重新创建时,会重新构建它所管理的Fragment,原先的Fragment的字段值将会全部丢失,但是通过Fragment.setArguments(Bundle bundle)方法设置的bundle会保留下来。所以尽量使用Fragment.setArguments(Bundle bundle)方式来传递参数
二、同一个Activity,不同container间的参数传递
这里到了这篇文章的重点内容了哦,这可并不是说上一部分不重要哈,其实上一部分要比这部分重要!同一个Container中不同Fragment间的参数传递一般的工程都会用到的,所以大家一定要看
这里有多种实现方法,最可取的是方法三。我们由简到易慢慢讲。
我们想使两个fragment实例要能通信,那如果我们都能通过findViewById()找到所有的控件,直接操控的话,岂不就实现了。而通过findViewById()能找到所有控件实例的地方就是在Activity中了,所以这就有了方法一。
方法一:直接在Activity中操作
可见,直接在activity中操作各个fragment的控件就可以实现消息互传。但,这样真的好吗?如果每个fragment中的控件都在Activity中操作,那还要fragment干嘛!最最起码,应该每个fragment负责自己的控件操作才对嘛!
所以,我们对这种方法进行改进,将点击Item的赋值操作放到fragment1中去。所以,这就有方法二;
方法二:直接在fragment中操作
在这里我们会把所有方法写在Fragment1中,这里涉及到两方面的内容:
第一:在Fragment中如何获得自己控件的引用,比较这里Fragment1里的listview控件。
第二:在Fragment中如何获得其它Fragment页面中控件的引用,比如这里Fragment2里的TextView控件。
首先,获取自己控件引用的方法:
方法一:在onCreateView()中获取。
由于在onCreateView()中,还没有创建视图,所以在这里如果使用getView()方法将返回空。所以如果要获取其实图中指定控件的引用,只用用inflater.inflate()返回的rootView;在这个rootView()中用findViewById来查找。
方法二:在onActivityCreated()函数中获取。
从《Fragment详解之一——概述》的流程图中可以看到,onActivityCreated()回调会在Activity的OnCreate()执行完成后再执行,也就是说,onActivityCreated()会在Activity的OnCreate()工作完成以后才会执行。所以当执行到onActivityCreated()的时候Activity已经创建完成,它其中的各个fragment也视图等等的也都已经创建完成。所在可以在这里获取跟Activity相关的各种资源。第二个问题中的获取其它Fragment页面中控件的引用也是在onActivityCreated()中来做的。先看看在onActivityCreated()中如何获得自己视图中控件的引用吧
然后,获得其它Fragment页面中控件的引用的方法
在上面已经说了,要获取Activity中的资源,就必须等Acitivity创建完成以后,所以必须放在onActivityCreated()回调函数中。
其获取方法为:
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mFragment2_tv = (TextView) getActivity().findViewById(R.id.fragment2_tv);//获取其它fragment中的控件引用的唯一方法!!!
}
我们这里直接在fragment1中操作了fragment2的控件,这样就违背了模块分离的思想,我们应该让他们各自处理各自的代码才好。所以,考虑到将他们分离,我们这里就出现了方法三。
方法三:在各自的fragment中操作
好,我们先想想要怎么解决这个问题,首先,我们把各自的事件放在各自的fragment中处理,即在fragment1中能得到当前用户点击的ITEM的String字符串,在fragment2中可以设置textview的值。那问题来了,各自获得了各自的东东,那通过什么让他们交互呢?
答案显然是activity。
很显然,在activity中可以直接通过FragmentManager::findFragmentById()来获取fragment2的实例。进而调用fragment2中的任意方法,这就实现了与fragment2的通信。
那fragment1又怎么把结果回传给Activity呢?大家如果在看到这里之前先看了《Fragment跳转时传递参数及结果回传的方法》就很容易想到,用回调!请记住。在不同页面中回传结果,回调是万能的解决方案。
Android - fragment Manager的更多相关文章
- Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误
嵌套Fragment的使用及常见错误 嵌套Fragments (Nested Fragments), 是在Fragment内部又添加Fragment. 使用时, 主要要依靠宿主Fragment的 ge ...
- Android Fragment 解析和使用
Android Fragment的生命周期和Activity类似,实际可能会涉及到数据传递,onSaveInstanceState的状态保存,FragmentManager的管理和Transactio ...
- Android Fragment用法详解(2)--动态添加Fragment
在上一篇文章<Android Fragment用法详解(1)--静态使用Fragment>我们讲解了Fragment的最简单的用法.这次我们来说一说Fragment复杂一丢丢的用法.在代码 ...
- Android 常用 Manager的总结
Android 常用 Manager的总结 1 smsManager 发送短信 --使用方法 --SmsManager smsManager = SmsManager.getDe ...
- Android编程权威指南笔记3:Android Fragment讲解与Android Studio中的依赖关系,如何添加依赖关系
Android Fragment 当我在学习时,了解了Fragment词汇 Fragment是一种控制器对象,我就把所了解的简单说一下.activity可以派fragment完成一些任务,就是管理用户 ...
- 【Android自学日记】【转】Android Fragment 真正的完全解析(下)
上篇博客中已经介绍了Fragment产生原因,以及一些基本的用法和各种API,如果你还不了解,请看:Android Fragment 真正的完全解析(上). 本篇将介绍上篇博客提到的:如何管理Frag ...
- Android SDK Manager 更新代理配置
转自:http://www.cnblogs.com/tao560532/p/4483067.html 出现问题: 消除SDK更新时,有可能会出现这样的错误:Download interrupted: ...
- Android Fragment使用(四) Toolbar使用及Fragment中的Toolbar处理
Toolbar作为ActionBar使用介绍 本文介绍了在Android中将Toolbar作为ActionBar使用的方法. 并且介绍了在Fragment和嵌套Fragment中使用Toolbar作为 ...
- Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复
Android中的状态保存和恢复 Android中的状态保存和恢复, 包括Activity和Fragment以及其中View的状态处理. Activity的状态除了其中的View和Fragment的状 ...
随机推荐
- Linux系统日志分析与管理(14)
当你的 Linux 系统出现不明原因的问题时,你需要查阅一下系统日志才能够知道系统出了什么问题了,所以说了解系统日志是很重要的事情,系统日志可以记录系统在什么时间.哪个主机.哪个服务.出现了什么信息等 ...
- 31_网络编程-struct
一.struct 1.简述 我们可以借助一个模块,这个模块可以把要发送的数据长度转换成固定长度的字节.这样客户端每次接收消息之前只要先接受这个固定长度字节的内容看一看接下来要接收的信息大小,那么 ...
- XSS 跨站脚本攻击 的防御解决方案
虽然说在某些特殊情况下依然可能会产生XSS,但是如果严格按照此解决方案则能避免大部分XSS攻击. 原则:宁死也不让数据变成可执行的代码,不信任任何用户的数据,严格区数据和代码. XSS的演示 Exam ...
- 纯css实现打字效果
概述 很早以前就在别人的博客上面看到打字动画了,觉得非常炫酷,以为是用js做的,找了半天也没找到js在哪里.今天看<css揭秘>,碰巧看到书上打字动画的实现了,而且是纯css实现的!我参考 ...
- flaks___git
今天呢 我给大家分享一个超实用的一个把代码分享到云端的一种操作 比如我们在家里,要想做项目的话可以直接从云端上拉取下来代码直接开始工作了 而且还可以随时修改,没有地点的局限性了,只要你想敲,随时随地 ...
- Vue2.5开发去哪儿网App 第三章笔记 下
1.样式的绑定 我们可以传给 v-bind:class 一个对象,以动态地切换 class 例如: :class="{activated:isactivated}" 上面的语法 ...
- the fist blood of java-eclipse 哈哈哈哈 封装的运用
class Student { private int id; public String name; public String sex; private int score ...
- PHP-引入文件(include)后,页面错位,不居中解决办法
1.把include文件放在head里,不要放在html或doctype上面,这样可以解决居中的问题,空白行的话可以用<div style="display:none"> ...
- 纯CSS3手风琴图片滑动特效
要求 必备知识 基本了解CSS语法,初步了解CSS3语法知识. 开发环境 Adobe Dreamweaver CS6/Chrome浏览器 演示地址 演示地址 制作CSS3制作手风琴图片滑动效果,我们仅 ...
- Spring mvc 4系列教程(二)——依赖管理(Dependency Management)和命名规范(Naming Conventions)
依赖管理(Dependency Management)和命名规范(Naming Conventions) 依赖管理和依赖注入(dependency injection)是有区别的.为了将Spring的 ...