热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Android】11.4Fragment及其生命周期

分类:C#、Android、VS2015;创建日期:2016-02-22一、简介Android从3.0开始引入了fragment的概念,主要是为了支持在大屏幕上实现更为动态和灵活的UI设计,比如

分类: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插入到activity的布局中,或者用C#代码将它添加到一个存在的ViewGroup中。然而,fragment并不是必须显示在activity布局中,它也可以在activity内隐身工作。

三、基本用法

Fragments有它自己独立的生命周期,如下图所示:

image

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);

    }

}


推荐阅读
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • 本文介绍如何在 Android 中自定义加载对话框 CustomProgressDialog,包括自定义 View 类和 XML 布局文件的详细步骤。 ... [详细]
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
  • Spring – Bean Life Cycle
    Spring – Bean Life Cycle ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
  • 零拷贝技术是提高I/O性能的重要手段,常用于Java NIO、Netty、Kafka等框架中。本文将详细解析零拷贝技术的原理及其应用。 ... [详细]
  • 在分析Android的Audio系统时,我们对mpAudioPolicy->get_input进行了详细探讨,发现其背后涉及的机制相当复杂。本文将详细介绍这一过程及其背后的实现细节。 ... [详细]
  • 实验九:使用SharedPreferences存储简单数据
    本实验旨在帮助学生理解和掌握使用SharedPreferences存储和读取简单数据的方法,包括程序参数和用户选项。 ... [详细]
  • 解决Bootstrap DataTable Ajax请求重复问题
    在最近的一个项目中,我们使用了JQuery DataTable进行数据展示,虽然使用起来非常方便,但在测试过程中发现了一个问题:当查询条件改变时,有时查询结果的数据不正确。通过FireBug调试发现,点击搜索按钮时,会发送两次Ajax请求,一次是原条件的请求,一次是新条件的请求。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 在软件开发过程中,经常需要将多个项目或模块进行集成和调试,尤其是当项目依赖于第三方开源库(如Cordova、CocoaPods)时。本文介绍了如何在Xcode中高效地进行多项目联合调试,分享了一些实用的技巧和最佳实践,帮助开发者解决常见的调试难题,提高开发效率。 ... [详细]
  • 在探讨如何在Android的TextView中实现多彩文字与多样化字体效果时,本文提供了一种不依赖HTML技术的解决方案。通过使用SpannableString和相关的Span类,开发者可以轻松地为文本添加丰富的样式和颜色,从而提升用户体验。文章详细介绍了实现过程中的关键步骤和技术细节,帮助开发者快速掌握这一技巧。 ... [详细]
  • 本文对比了杜甫《喜晴》的两种英文翻译版本:a. Pleased with Sunny Weather 和 b. Rejoicing in Clearing Weather。a 版由 alexcwlin 翻译并经 Adam Lam 编辑,b 版则由哈佛大学的宇文所安教授 (Prof. Stephen Owen) 翻译。 ... [详细]
  • 重要知识点有:函数参数默许值、盈余参数、扩大运算符、new.target属性、块级函数、箭头函数以及尾挪用优化《深切明白ES6》笔记目次函数的默许参数在ES5中,我们给函数传参数, ... [详细]
  • 本文详细解析了使用C++实现的键盘输入记录程序的源代码,该程序在Windows应用程序开发中具有很高的实用价值。键盘记录功能不仅在远程控制软件中广泛应用,还为开发者提供了强大的调试和监控工具。通过具体实例,本文深入探讨了C++键盘记录程序的设计与实现,适合需要相关技术的开发者参考。 ... [详细]
author-avatar
邱walz_297
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有