文档章节

Fragment生命周期详解

htq
 htq
发布于 2016/07/26 09:39
字数 1857
阅读 4
收藏 0
点赞 0
评论 0

关于Fragment的生命周期,博主写过Activity与Fragment生命周期详解,基本上把Fragment的生命周期详细介绍过,但是那仅仅是创建一个Fragmnet时的生命周期,而事实上Fragment的出现是为了动态的切换显示不同的界面的,因此我们对于Fragment的生命周期的了解不能仅仅停留在创建一个Fragment的时候,而是应该能够知道调用不同API切换Fragment时的生命周期是怎么的,如调用add(),hide(),show()与replace()时它们的生命周期的不同,博主在昨天360视频面试的时候就被问到过。

一使用静态方式时的生命周期:

正如我们在Activity与Fragment生命周期详解中所介绍的,此时Fragment的生命周期为

onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach.

可以参看Activity与Fragment生命周期详解中相关内容的官方图片理解,

1其中当创建一个Fragment首次展示其布局界面时:

onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态

2当关闭手机屏幕或者手机屏幕变暗或直接按home键返回桌面时,其生命周期方法调用的顺序是

onPause, onStop

3当再次对手机屏幕解锁或者手机屏幕变亮时,其生命周期方法调用的顺序:

onStart, onResume

4当对Fragment按返回键时:

onPause, onStop, onDestroyView, onDestroy, onDetach.


二使用FragmentManager动态的添加Fragment

这块是本博客讲解的重点,因为动态添加涉及到Fragment的切换,所以我们先定义两个Fragment。代码如下:

public class FragOne extends Fragment {
    private static final String TAG = FragOne.class.getSimpleName();

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        Log.i(TAG, "onAttach");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.i(TAG, "onCreateView");
        return inflater.inflate(R.layout.fragment_test_a, null, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        Log.i(TAG, "onViewCreated");
        super.onViewCreated(view, savedInstanceState);
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy");
        super.onDestroy();
    }

    @Override
    public void onDetach() {
        Log.i(TAG, "onDetach");
        super.onDetach();
    }

    @Override
    public void onDestroyView() {
        Log.i(TAG, "onDestroyView");
        super.onDestroyView();
    }

    @Override
    public void onStart() {
        Log.i(TAG, "onStart");
        super.onStart();
    }

    @Override
    public void onStop() {
        Log.i(TAG, "onStop");
        super.onStop();
    }

    @Override
    public void onResume() {
        Log.i(TAG, "onResume");
        super.onResume();
    }

    @Override
    public void onPause() {
        Log.i(TAG, "onPause");
        super.onPause();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        Log.i(TAG, "onActivityCreated");
        super.onActivityCreated(savedInstanceState);
    }
}
第二个Fragment

public class FragTwo extends Fragment {
    private static final String TAG = FragTwo.class.getSimpleName();

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        Log.i(TAG, "onAttach");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.i(TAG, "onCreateView");
        return inflater.inflate(R.layout.fragment_test_b, null, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        Log.i(TAG, "onViewCreated");
        super.onViewCreated(view, savedInstanceState);
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy");
        super.onDestroy();
    }

    @Override
    public void onDetach() {
        Log.i(TAG, "onDetach");
        super.onDetach();
    }

    @Override
    public void onDestroyView() {
        Log.i(TAG, "onDestroyView");
        super.onDestroyView();
    }

    @Override
    public void onStart() {
        Log.i(TAG, "onStart");
        super.onStart();
    }

    @Override
    public void onStop() {
        Log.i(TAG, "onStop");
        super.onStop();
    }

    @Override
    public void onResume() {
        Log.i(TAG, "onResume");
        super.onResume();
    }

    @Override
    public void onPause() {
        Log.i(TAG, "onPause");
        super.onPause();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        Log.i(TAG, "onActivityCreated");
        super.onActivityCreated(savedInstanceState);
    }
}
可以看到这两个Fragment的代码基本上完全相同,都是重写了Fragment中相关的生命周期函数。


一当没使用addToBackStack函数时。

1使用replace()函数时:

当我们使用replace初次显示一个Fragment时,此时代码如下:

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
 fragOne = new FragOne();
 fragmentTransaction.replace(R.id.frag_container, fragOne, fragNames[0]);
 fragmentTransaction.commit();
此时的生命周期和上述讲述的完全相同,即onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态。


当我们使用replace()来替换一个已经存在的Fragment时(如腾讯QQ中当我们点击不同的底部按钮时会替换之前的Fragment),此时代码如下:

public void onClick(View v) {
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        switch (v.getId()) {
            case R.id.button1:
                if (fragOne == null) {
                    fragOne = new FragOne();
                    fragmentTransaction.replace(R.id.frag_container, fragOne, fragNames[0]);
//                    fragmentTransaction.addToBackStack(fragNames[0]);
                } else {
                    Fragment fragment = fragmentManager.findFragmentByTag(fragNames[0]);
                    fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[0]);
                }
                break;
            case R.id.button2:
                if (fragTwo == null) {
                    fragTwo = new FragTwo();
                    fragmentTransaction.replace(R.id.frag_container, fragTwo, fragNames[1]);
//                    fragmentTransaction.addToBackStack(fragNames[1]);
                } else {
                    Fragment fragment = fragmentManager.findFragmentByTag(fragNames[1]);
                    fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[1]);
                }
                break;
            default:
                break;
        }
        fragmentTransaction.commit();
    }
可以看到在上述代码中,我们将addToBackStack函数的调用注释起来,表示此时不适用该功能。此时的运行顺序为:


可以看到第一个Fragment的调用顺序为:onPause, onStop, onDestroyView, onDestroy, onDetach,这表明fragOne已经被FragmentManager销毁了,取而代之的是第二个Fragment,这也与replace()函数的名称和不适用addToBackStack相符合(即替换且不添加到Fragment返回栈中,既然是替换当然得去除前一个,添加第二个Fragment)

这说明,在使用replace添加Fragment时如果没有调用addToBackStack方式的话,当FragmentManager替换Fragment时,是不保存Fragment的状态的,此时第二个Fragment将会直接替换前一个Fragment。

二使用addToBackStack函数时。

当我们使用replace函数且设置addToBackStack函数初次显示一个Fragment运行结果为:onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态。即与不使用addToBackStack函数时的运行结果相同。

当我们使用replace函数且设置addToBackStack函数来替换之前显示的Fragmen't时运行结果为:


可以看到与之前的不使用addToBackStack相比,fragTwo的生命周期不受影响,而fragOne的生命周期和不使用addBackToStack函数相比,只存在三种状态的切换:onPause

onStop,onDestroyView。前者很好理解,因为addToBackStack函数顾名思义就是添加到回退栈中的意思,即当一个Fragment被另一个Fragment替换时会将之前的添加到回退栈中,因此也很好理解fragTwo的生命周期不受影响,因为是将被替换的添加到回退栈中,所以替换者不受影响。另外fragOne状态只到达onDestroyView,而无onDestroy,

onDetach。这说明fragOne仅仅只是界面被销毁onDestroyView,而fragOne对象的实例依然被保存在FragmentManager中(因为无onDestroy,onDetach),它的部分状态依然被保存在FragmentManager中。我们可以来验证一下:


我们点击按钮切换,让fragOne来替换当前显示的fragTwo,此时运行结果如下:


可以看到此时运行结果与fragTwo替换fragOne时fragOne的生命周期调用顺序非常相似,而且可以看到fragOne的生命周期是直接从onCreateView开始的,这也刚好对应上面的fragOne被fragTwo替换时生命周期到达onDestroyView,即之前的fragOne仅仅销毁了视图,而fragOne对象的实例依然被保存在FragmentManager中,所以此时只需要创建视图,即直接从onCreateView开始。


三使用show()/hide()函数时:首先要明白使用show()/hide()时一般是会使用addToBackStack,,因为要使用show()/hide()前提是该Fragment实例已经存在,只不过我们是否将其界面显示出来而已,因此我们需要使用addToBackStack函数将一个Fragment的实例对象保存在Fragment的回退栈中。此时代码如下:

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        switch (v.getId()) {
            case R.id.button1:
                hideAllFrags(fragmentTransaction);
                if (fragA == null) {
                    fragOne = new FragOne();
                    fragmentTransaction.add(R.id.frag_container, fragOne, fragNames[0]);
                    fragmentTransaction.addToBackStack(fragNames[0]);
                } else {
                    fragmentTransaction.show(fragOne);
                }
                break;
            case R.id.button2:
                hideAllFrags(fragmentTransaction);
                if (fragTwo == null) {
                    fragTwo = new FragTwo();
                    fragmentTransaction.add(R.id.frag_container, fragTwo, fragNames[1]);
                    fragmentTransaction.addToBackStack(fragNames[1]);
                } else {
                    fragmentTransaction.show(fragTwo);
                }
                break;
            default:
                break;
        }
fragmentTransaction.commit();

当我们使用add()/show()函数初次显示一个Fragment运行结果为:onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态。这个很好理解,不再赘述。

当我们点击按钮切换显示第二个Fragment时运行结果为:


可以看到此时fragOne无输出,表示fragOne的生命周期不受影响,而fragTwo的输出结果与直接初次显示fragTwo时是一样的。其实这也很好理解因为在add()/show()/hide()顾名思义就是添加显示隐藏的意思,它都不会对另外的Fragment的生命周期起作用。



本文转载自:http://blog.csdn.net/htq__/article/details/51210306

共有 人打赏支持
htq

htq

粉丝 19
博文 67
码字总数 1007
作品 3
武汉
Fragment详解

相关文章: 1、《Fragment详解之一——概述》 2、《Fragment详解之二——基本使用方法》 3、《Fragment详解之三——管理Fragment(1)》 4、《Fragment详解之四——管理Fragment(2)》 5、《...

我叫leo- ⋅ 2016/04/08 ⋅ 0

android Fragments详解六:处理fragement的生命周期

把条目添加到动作栏 你的fragment们可以向activity的菜单(按Manu键时出现的东西)添加项,同时也可向动作栏(界面中顶部的那个区域)添加条目,这都需通过实现方法onCreateOptionManu()来完...

jxlgzwh ⋅ 2013/07/19 ⋅ 0

android Fragments详解六:处理fragement的生命周期

把条目添加到动作栏 你的fragment们可以向activity的菜单(按Manu键时出现的东西)添加项,同时也可向动作栏(界面中顶部的那个区域)添加条目,这都需通过实现方法onCreateOptionManu()来完...

晨曦之光 ⋅ 2012/03/12 ⋅ 0

Glide使用详解

引入 以androidStudio为例,在build.gradle中添加依赖: AndroidManifest.xml中声明一下网络权限: 使用 1加载图片 先with(),再load(),最后into(),这是最简单的三部曲 Glide.with()使用: w...

five519 ⋅ 2017/11/16 ⋅ 0

android Fragments详解二:创建Fragment

创建Fragment 要创建fragment,必须从Fragment或Fragment的派生类派生出一个类。Fragment的代码写起来有些像activity。它具有跟activity一样的回调方法,比如 onCreate(),onStart(),onPause...

晨曦之光 ⋅ 2012/03/12 ⋅ 0

android Fragments详解一:概述

Fragment是activity的界面中的一部分或一种行为。你可以把多个Fragment们组合到一个activity中来创建一个多面界面并且你可以在多个activity中重用一个Fragment。你可以把Fragment认为模块化的...

晨曦之光 ⋅ 2012/03/12 ⋅ 0

Fragment 的生命周期及使用方法详解

Fragment 的基础知识介绍 1.1 概述 1.1.1 特性 By hebang32624 Fragment 是 activity 的界面中的一部分或一种行为。可以把多个 Fragment 组合到一个 activity 中来创建一 个多面界面并且可以...

梁DH ⋅ 2013/04/25 ⋅ 2

android开发之Fragment 的生命周期及使用方法详解

Fragment 的基础知识介绍 1.1 概述 1.1.1 特性 ragment 是 activity 的界面中的一部分或一种行为。可以把多个 Fragment 组合到一个 activity 中来创建一 个多面界面并且可以在多个 activity...

you缘么 ⋅ 2016/04/28 ⋅ 0

Android Fragment 使用详解

有关Android Fragment相关内容,我们在Fragment对比Activity - Android碎片介绍一文简单讲了下Fragment的作用以及它的生命周期,今天主要讲些Fragment的管理控制、性能优化以及和Activity的传...

鉴客 ⋅ 2011/12/12 ⋅ 0

Architecture Components MVVM架构演进

在对MVP的架构实践中,发现写单元测试不是那么方便,因为Presenter持有了View的引用,而Mock View的 行为和方法特别的卡慢,因此只能把具体的业务逻辑再抽成一个个独立于Presenter的Logic,进...

Mr云台 ⋅ 2017/11/27 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

MySQL 数据库设计总结

规则1:一般情况可以选择MyISAM存储引擎,如果需要事务支持必须使用InnoDB存储引擎。 注意:MyISAM存储引擎 B-tree索引有一个很大的限制:参与一个索引的所有字段的长度之和不能超过1000字节...

OSC_cnhwTY ⋅ 今天 ⋅ 0

多线程(四)

线程池和Exector框架 什么是线程池? 降低资源的消耗 提高响应速度,任务:T1创建线程时间,T2任务执行时间,T3线程销毁时间,线程池没有或者减少T1和T3 提高线程的可管理性。 线程池要做些什...

这很耳东先生 ⋅ 今天 ⋅ 0

使用SpringMVC的@Validated注解验证

1、SpringMVC验证@Validated的使用 第一步:编写国际化消息资源文件 编写国际化消息资源ValidatedMessage.properties文件主要是用来显示错误的消息定制 [java] view plain copy edit.userna...

瑟青豆 ⋅ 今天 ⋅ 0

19.压缩工具gzip bzip2 xz

6月22日任务 6.1 压缩打包介绍 6.2 gzip压缩工具 6.3 bzip2压缩工具 6.4 xz压缩工具 6.1 压缩打包介绍: linux中常见的一些压缩文件 .zip .gz .bz2 .xz .tar .gz .tar .bz2 .tar.xz 建立一些文...

王鑫linux ⋅ 今天 ⋅ 0

6. Shell 函数 和 定向输出

Shell 常用函数 简洁:目前没怎么在Shell 脚本中使用过函数,哈哈,不过,以后可能会用。就像java8的函数式编程,以后获取会用吧,行吧,那咱们简单的看一下具体的使用 Shell函数格式 linux ...

AHUSKY ⋅ 今天 ⋅ 0

单片机软件定时器

之前写了一个软件定时器,发现不够优化,和友好,现在重写了 soft_timer.h #ifndef _SOFT_TIMER_H_#define _SOFT_TIMER_H_#include "sys.h"typedef void (*timer_callback_function)(vo...

猎人嘻嘻哈哈的 ⋅ 今天 ⋅ 0

好的资料搜说引擎

鸠摩搜书 简介:鸠摩搜书是一个电子书搜索引擎。它汇集了多个网盘和电子书平台的资源,真所谓大而全。而且它还支持筛选txt,pdf,mobi,epub、azw3格式文件。还显示来自不同网站的资源。对了,...

乔三爷 ⋅ 今天 ⋅ 0

Debian下安装PostgreSQL的表分区插件pg_pathman

先安装基础的编译环境 apt-get install build-essential libssl1.0-dev libkrb5-dev 将pg的bin目录加入环境变量,主要是要使用 pg_config export PATH=$PATH:/usr/lib/postgresql/10/bin 进......

玛雅牛 ⋅ 今天 ⋅ 0

inno安装

#define MyAppName "HoldChipEngin" #define MyAppVersion "1.0" #define MyAppPublisher "Hold Chip, Inc." #define MyAppURL "http://www.holdchip.com/" #define MyAppExeName "HoldChipE......

backtrackx ⋅ 今天 ⋅ 0

Linux(CentOS)下配置php运行环境及nginx解析php

【part1:搭建php环境】 1.选在自己需要安装的安装包版本,wget命令下载到服务器响应目录 http://php.net/releases/ 2.解压安装包 tar zxf php-x.x.x 3.cd到解压目录执行如下操作 cd ../php-...

硅谷课堂 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部