热门标签 | 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);

    }

}


推荐阅读
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • C# WPF自定义按钮的方法
    本文介绍了在C# WPF中实现自定义按钮的方法,包括使用图片作为按钮背景、自定义鼠标进入效果、自定义按压效果和自定义禁用效果。通过创建CustomButton.cs类和ButtonStyles.xaml资源文件,设计按钮的Style并添加所需的依赖属性,可以实现自定义按钮的效果。示例代码在ButtonStyles.xaml中给出。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文介绍了在Linux下安装Perl的步骤,并提供了一个简单的Perl程序示例。同时,还展示了运行该程序的结果。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
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社区 版权所有