【Android】11.4 Fragment及其生命周期
分类:C#、Android、VS2015;
创建日期:2016-02-22
一、简介
Android从3.0开始引入了fragment的概念,主要是为了支持在大屏幕上实现更为动态和灵活的UI设计,比如平板电脑等。由于平板电脑的屏幕要比手机屏幕大许多,这样就有更多的空间去组合和交换UI组件。
也许这样比喻你能更快地理解它:和WPF相比,如果将Activity的作用看作类似于WPF的Window或者Page;那么Fragments的作用就类似于WPF在Window或者Page中包含的一个或多个Frame元素。
本节将分别描述:
- 如何用fragment来创建Android应用程序,包括将fragment添加到后台栈时如何维护其状态;
- 如何在同一个activity中让多个属于该activity的fragment共享事件;
- 如何将多个fragment构建到activity的动作槽(action bar)中;
等等。
二、基本概念
Fragment表现Activity中用户界面的一个行为或者是一部分行为。你可以在一个单独的activity上把多个fragment组合成一个多区域的UI,并且可以在多个activity中重复使用。可以将fragment看作是activity的一个模块组件,它有自己的生命周期,接收它自己的输入事件,并且可以在activity运行时被添加或者删除。
1、Fragment必须被嵌入到一个activity中才能使用
Fragment必须被嵌入到一个activity中才能使用,并且fragment的生命周期直接受其宿主activity的生命周期的影响。
例如,一旦某个activity被暂停,它里面所有的fragment也都被暂停,一旦某个activity被销毁,它里面所有的fragment也会被销毁。但是,当activity正在运行时(处于resumed的生命周期状态),你可以单独操控每个fragment,比如添加或者删除某个fragment。当你执行这样一项事务时,可以将它添加到一个后台栈中,这个栈由activity管理着——activity里面的每个后台栈内容实体是fragment发生过的一条事务记录。这个后台栈允许用户通过按【Back】键(向后导航)回退一项fragment事务。
2、fragment的作用就是将activity的布局分割成若干个部分
将activity的布局分割成若干个fragment后,就可以在运行时控制activity的呈现,并且那些变化会被保存在由activity管理的后台栈中。
例如,新闻应用程序将一个fragment放在左边显示文章列表,右边用另一个fragment来显示一篇文章,此时两个fragment都在同一个activity中,并且每个fragment都有其自己的生命周期回调方法序列,用以处理各自的用户输入事件。因此,用户可以在同一个activity中选择和阅读文章,而不是在一个activity中选择文章,却在另一个activity中去阅读。
3、可在多个activity中引用同一个fragment
应该将每一个fragment设计为模块化的和可复用化的activity组件。也就是说,可以在多个activity中引用同一个fragment,这是因为fragment定义了它自己的布局,并且使用它本身生命周期回调的行为。这点尤为重要,原理很简单,模块化和复用能让你改变fragment组合以满足不同的屏幕尺寸。
设计同时支持平板电脑和手机的应用时,通过不同的布局配置可,就可以复用fragments。例如,在手机上,当同一个activity不能容纳更多的fragment时,可能需要通过分离fragments提供一个单区域的界面。
再例如,仍以新闻应用程序为例,当程序运行在平板屏幕设备上时,可以在Activity A中嵌入两个fragment。但是,当运行在手机屏幕上,就没有足够的空间同时容纳两个fragment了,因此Activity A只能引用包含文章列表的fragment,在当用户选择其中的一篇文章标题时,就可以启动Activity B,它包含了用来阅读文章的第二个fragment。这样,应用程序通过组合不同的fragments,就可以达到复用的目的,这样就能同时支持平板电脑和手机。
当将一个fragment作为某个activity布局的一部分时,它就存在于这个activity视图体系内部的ViewGroup中,并且定义了它自己的视图布局。可以在activity布局文件中用<fragment>元素把fragment插入到activity的布局中,或者用C#代码将它添加到一个存在的ViewGroup中。然而,fragment并不是必须显示在activity布局中,它也可以在activity内隐身工作。
三、基本用法
Fragments有它自己独立的生命周期,如下图所示:
1、创建一个Fragment时引发的回调方法
下面介绍创建一个Fragment时引发的回调方法。
(1)Infalate()【常用】
Infalate:充气式膨胀填充,说白了也就是Fill时宽高都填满的意思。
当创建一个Fragment时,可以重写OnCreateView(),通过OnCreateView()返回一个布局,然后再将其填充(inflate)到XML(或AXML)的布局文件中。为了便于你这样做,OnCreateView()提供了一个LayoutInflater对象。
例如,下面是一个fragment子类,它的布局是从example_fragment.xml载入的:
public static class ExampleFragment : Fragment
{
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// 将fragment填充(Inflate)到布局中
return inflater.inflate(Resources.layout.example_fragment, container, false);
}
}
传入OnCreateView()的参数container 是你的frament布局将要被插入的父ViewGroup(来自activity的布局)。如果fragment处于resumed状态(恢复状态在操纵fragment生命周期中将作更多讨论),参数savedInstanceState是Bundle类的实例,它提供了fragment之前实例的相关数据。
Inflate()方法需要以下3个参数:
- 要填充(inflate)的布局资源的ID。
- 被填充的布局的父ViewGroup。传入container很重要,这是为了让系统将布局参数应用到被inflate的布局的根view中去,由将要嵌入的父view来指定。
- 一个布尔值,表明在inflate期间被infalte的布局是否应该附上ViewGroup(第二个参数)。(在这个例子中传入的是false,因为系统已经将被inflate的布局插入到container容器中——传入true会在最终的布局里创建一个多余的ViewGroup)。
创建fragment以后,就可以将这个fragment添加到activity中了。
(2)OnAttach()
当Fragment与Activity关联之后会调用此方法。这是Fragment准备好后运行的第一个方法。
一般情况下,不要重写Fragments默认的构造函数,也不要为其实现新的构造函数。这是因为在OnAttach()方法中,Fragments所需的任何组件都可能被重新初始化,这可能会导致在构造函数中所做的工作失效。
(3)OnCreate()【常用】
执行OnAttach()以后,系统会接着调用OnCreate()方法。在重写此方法的实现代码中,可以初始化想在fragment中保持的那些必要组件,当fragment处于暂停或者停止状态之后可重新启用它们。
当系统调用OnCreate()方法时,宿主Activity的层次视图可能不会被完全实例化,所以fragment不应再此方法中依赖活动视图层次结构的任何部分。例如,不要在此方法中执行对UI或应用程序的任何调整。
OnCreate()是Fragment开始收集所需数据的最早时期。此时Fragment运行在UI线程上,所以应该避免任何长时间的处理,如果运行时间确实很长,可考虑在后台线程上执行该处理。
如果调用了SetRetainInstance(true)方法,此方法可能会被跳过。替代方法将在后面详细描述。
(4)OnCreateView()
OnCreate()完成后系统会调用此方法,用于为fragment绘制用户界面。该方法需要返回fragment使用的View。如果fragment没有用户界面,则返回null。
(5)OnActivityCreated()
当OnCreate()已完成并被Activity托管(或者称宿主到Activity中)时,系统将调用此方法。这是将fragment调整到用户界面上显示之前最后执行的方法。
(6)OnStart()
当恢复包含的Activity时系统将调用此方法,此时该fragment对用户可见。在许多情况下,该片段将包含它应该执行的代码,或者在Activity的OnStart()方法中包含它应该执行的代码。
(7)OnResume()
这是用户可以与片段交互之前最后调用的方法。比如,在此方法中启用相机设备、位置服务等功能。不过,由于这些服务会导致电池消耗很快,一般应尽量减少使用这类应用以延长电池的寿命。
2、销毁一个Fragment时引发的回调方法
下面介绍销毁一个Fragment时引发的回调方法。
(1)OnPause()【常用】
当调用OnPause()以后,用户将无法再与该片段进行交互。之所以存在这种情况,是因为一些其他的片段操作修改了此片段,或托管活动(hosting Activity)已暂停。此时,承载此片段的活动很可能仍然可见,比如,获得焦点的活动是部分透明的或该片段并不占用整个屏幕就是这种情况。
当激活此方法时,它是用户离开该Fragment的第一个预兆(尽管这并不总意味着fragment被销毁)。在当前用户会话结束之前,通常要在这里提交任何应该持久化的变化(因为用户可能不再返回)。
(2)OnStop()
该Fragment不再可见。此时托管的活动主机可能已经停止,或者在活动中修改了进行的片段。此回调方法与Activity的OnStop()用途相同。
(3)OnDestroyView()
当与片段关联的视图被销毁时,系统将调用此方法清理与视图关联的资源。
(4)OnDestroy()
当不再使用该片段时将调用此方法。此时该片段仍然与活动关联,但不再具有功能。此方法应该释放片段正在使用的资源,例如相机使用的SurfaceView等。
如果调用了SetRetainInstance(true)方法,此方法可能会被跳过。替代方法将在后面再详细描述。
(5)OnDetach()
这是片段不再与活动关联之前调用的方法。该片段的视图层次将不存在,此时片段所使用的所有资源都应该在此处被释放。
(6)使用SetRetainInstance()方法
当重建某个活动时,有时候你可能希望不销毁指定的某个片段,在这种情况下,可以调用SetRetainInstance()方法来实现这个目的。如果传递给此方法的参数为true,当重启该活动时,系统将使用同一个Fragment实例。如果发生这种情况,在Fragment的生命周期中,将不再调用OnCreate()和OnDestroy(),但是仍会调用其他的回调方法。这一过程在上面的生命周期图示中用“绿色的虚线”标识了出来。
3、Fragment的状态管理
在Fragments的生命周期中,可通过Bundle实例保存或恢复Fragment的状态,由于Bundle实例存储的仅仅是字符串形式的“键/值”对,因此并不需要占用太多的内存。例如:
public override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
outState.PutInt("current_choice", currentCheckPosition);
}
创建Fragment的实例后,即可在重写的OnActivityCreated()中读取该实例的状态。例如:
public override void OnActivityCreated(Bundle savedInstanceState)
{
base.OnActivityCreated(savedInstanceState);
if (savedInstanceState != null)
{
currentCheckPosition = savedInstanceState.GetInt("current_choice", 0);
}
}
【Android】11.4 Fragment及其生命周期的更多相关文章
- Android成长日记-Fragment的生命周期与Activity通信
1. public void onAttach(Activity activity) 当Fragment被添加到Activity时候会回调这个方法,并且这个方法只会被回调一次 2. public vo ...
- Android系列之Fragment(二)----Fragment的生命周期和返回栈
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- Android学习笔记(六)Fragment的生命周期
在上一篇博文中对Fragment做了简单的介绍,现在再来探讨一下Fragment的生命周期. 一.Fragment的几种状态: 与Activity类似,Fragment也有一下几种状态: · 活动状态 ...
- 测试Activity和Fragment的生命周期
Activity的生命周期有7个函数,Fragment的生命周期有11个函数. Activity生命周期除上述6个方法还有一个Restart()方法,该方法在该Activity从不可见(仍存在)到重新 ...
- Fragment的生命周期
Fragment的生命周期: 1. onAttach():Fragment对象跟Activity关联时 2. onCreate():Fragment对象的初始创建时 3. onCreateView() ...
- Fragment的生命周期(三)
自定义lifecycleoffragment布局文件 在main_activity布局中引用自定义的fragment布局 到logcat中查看程勋运行的结果 代码如下: 自定义的fragment布局: ...
- fragment的生命周期及其各个周期方法的作用
先上生命周期图: Fragment的生命周期图: 与Activity的生命周期对比图: 由于Fragment是嵌在Activity中使用的,故其生命周期也是依赖于Activity的周期的,或者说Fra ...
- Fragment的生命周期&同一Activity下不同Fragment之间的通信
Android开发:碎片Fragment完全解析(2) Fragment的生命周期 和Activity一样,Fragment也有自己的生命周期,理解Fragment的生命周期非常重要,我们通过代码的方 ...
- Fragment 的生命周期及使用方法详解
Fragment 的基础知识介绍 1.1 概述 1.1.1 特性 By hebang32624 Fragment 是 activity 的界面中的一部分或一种行为.可以把多个 Fragment 组合到 ...
随机推荐
- linux下线程调试 ulimit core
在linux 下写线程程序的同学预计都遇到过找bug找到崩溃的情况.多线程情况下bug的追踪实在是不easy. 如今我来介绍一个好用的方法 ulimit core. 先简介一下ulimit是个什么(你 ...
- JavaScript 之 对象和数组
一:对象 说起对象,我们不自然就想起了面向对象中自封装的一个类,同样JS中也是遵循这个守则,在web编程中几乎天天用到的就是JSON.是的,这就是一个对象,不过这个对象下面的字段都是字符串和值类型 ...
- git 使用流程(使用代码库github)
一:先在github 上注册账号,并创建一个项目: 二:mac 命令行-进入自己的工作空间 1:建立库 git init 2:初始化配置 git config --global user.na ...
- Wireshark基本介绍和TCP三次握手
转自:http://www.cnblogs.com/TankXiao/archive/2012/10/10/2711777.html 之前写过一篇博客:用 Fiddler 来调试HTTP,HTTPS. ...
- IO习题
1.Java实现将九九乘法表输入到文本文件 public class Test1 { public static void main(String[] args) throws FileNotFoun ...
- git检查与放弃本地的代码修改情况
git diff 可以查看当前没有add 的内容修改(不在缓冲区的文件变化) git diff --cached查看已经add但没有commit 的改动(在缓冲区的文件变化) git diff HE ...
- 如何自定义oauthauthorizationserverprovider错误信息?
We are using the OAuthAuthorizationServerProvider class to do authorization in our ASP.NET Web Api a ...
- 微博混合云DCP:极端流量下的峰值应对与架构挑战
摘要: 在2016杭州云栖大会的“开发者技术峰会”上,来自新浪微博的资深运维架构师王关胜带来题为<微博混合云DCP:极端流量下的峰值应对与架构挑战>的精彩分享,分享中他从微博业务背景及峰值 ...
- 利用ASP.NET一般处理程序动态生成Web图像(转)
摘自:http://www.cnblogs.com/zhouhb/archive/2011/02/15/1955262.html 一般处理程序的扩展名为ashx,它实现了IHttpHandler接口, ...
- FastJSON使用案例(fastjson-1.1.28.jar)
import java.util.List; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; ...