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

    }

}


推荐阅读
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 在开发app时,使用了butterknife后,在androidStudio打包apk时可能会遇到报错。为了解决这个问题,可以通过打开proguard-rules.pro文件进行代码混淆来解决。本文介绍了具体的混淆代码和方法。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • 如何在HTML中获取鼠标的当前位置
    本文介绍了在HTML中获取鼠标当前位置的三种方法,分别是相对于屏幕的位置、相对于窗口的位置以及考虑了页面滚动因素的位置。通过这些方法可以准确获取鼠标的坐标信息。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 本文介绍了Python函数的定义与调用的方法,以及函数的作用,包括增强代码的可读性和重用性。文章详细解释了函数的定义与调用的语法和规则,以及函数的参数和返回值的用法。同时,还介绍了函数返回值的多种情况和多个值的返回方式。通过学习本文,读者可以更好地理解和使用Python函数,提高代码的可读性和重用性。 ... [详细]
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社区 版权所有