Activity和Fragment的生命周期总结以及保存实例状态机制

news2025/2/25 5:10:49

读完将收获以下内容

一. Activity的生命周期详解
Activity配置和状态改变时生命周期
Activity状态和配置改变时的解决方案
二.Fragment的生命周期详解
Fragment配置和状态改变时生命周期
Fragmen状态和配置改变时的解决方案
三.Activity和Fragment的生命周期调用顺序

一. Activity的生命周期详解

生命周期基础

详细可以看:

Activity生命周期

Activity配置和状态改变时生命周期

背景:

如果系统由于系统约束(而不是正常的应用程序行为)而破坏了Activity,那么尽管实际 Activity实例已经消失,但是系统还是会记住它已经存在,这样如果用户导航回到它,系统就会创建一个新的Activity实例,并使用一组保存的数据来描述Activity在被销毁时的状态。系统用于恢复以前状态的已保存数据称为“实例状态”,是存储在Bundle对象中的键值对的集合(IPC 对 Bundle 有 1M 的限制,不宜存放大内存数据,viewmodel的存放数据能力也是它的一个优势)

不正常销毁解决方案:

onSaveInstanceState(@NonNull Bundle outState)

onRestoreInstanceState()

在这里插入图片描述

Activity提供了上面这俩个方法来解决 Activity的不正常销毁。

简单使用:

  1. 重写 onSaveInstanceState
    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
    //利用outstate保存需要的数据
        outState.putString("text",(String) mtv.getText());
        Log.d("jian", "Activity onSaveInstanceState: ");
    //outState.putSerializable("fragment",fragment);
        super.onSaveInstanceState(outState);
    // 调用父类交给系统处理,这样系统能保存视图层次结构状态
    }

  1. 在onCreate(@Nullable Bundle savedInstanceState) 中:
       //savedInstanceState就是onCreate的参数了
       //在oncreate中,savedInstanceState可能为null,所以需要判空
        if(savedInstanceState != null){
            String text = savedInstanceState.getString("text");
            mtv.setText(text);
        }

或者在onRestoreInstanceState(@NonNull Bundle savedInstanceState) 中:
onRestoreInstanceState 只有在activity被系统回收或是销毁的时候.重新创建activity的情况下才会被调用。

           //注意这个方法里的savedInstanceState一定不为null
           //因为只有在Activity被不正常销毁后重建的时候才会调用,所以此时方法参数一定不为null,因此不需要判空
           
            super.onRestoreInstanceState(savedInstanceState);            
            // 总是调用超类,以便它可以恢复视图层次超级
            String text = savedInstanceState.getString("text");
            mtv.setText(text);

onCreate和onRestoreInstanceState方法的区别:

  • 因为onSaveInstanceState 不一定会被调用,所以onCreate()里的Bundle参数可能为空,如果在onCreate中来恢复数据,savedInstanceState一定要做非空判断。

  • onRestoreInstanceState的Bundle参数一定不会是空值,因为它只有在上次activity被回收了才会调用。

  • onRestoreInstanceState是在onStart()之后被调用的。有时候我们需要onCreate()中做的一些初始化完成之后再恢复数据,用onRestoreInstanceState会比较方便。
    简单看一下Activity生命周期方法的调用顺序:

  • 刚打开Activity:
    onCreate --> onStart --> onResume
    在这里插入图片描述

  • 旋转屏幕时:
    onPause --> onSaveInstanceState --> onStop–> onDestroy --> onCreate --> onStart --> onRestoreInstanceState–> onResume
    在这里插入图片描述

  • 按下返回键时:
    其实按下返回键时,系统调用的是finish()
    onPause-> onStop–> onDestroy
    在这里插入图片描述

  • 按下返回键后再重新打开activity
    onCreate --> onStart --> onResume
    在这里插入图片描述
    所以综上可知,

  • 按下返回键系统调用的是finish,另外,不管是按下返回键(系统调用了finish() )或者用户自己调用finish() 都是属于正常关闭activity,因此onSaveInstanceState()方法 此时不会调用,当此时重新进入(创建) activity时,onRestoreInstanceState(@NonNull Bundle savedInstanceState)方法也不会被调用

  • 不管是按下返回键(系统调用了finish() )或者用户自己调用finish() 都是属于正常关闭activity/fragment,此时activity/fragment都是会被销毁onDestory,重新进入时会onCreate,此时创建的实例与销毁前的实例不一样

配置状态改变时解决方案:

onRetainNonConfigurationInstance

public final Object onRetainNonConfigurationInstance() 

getLastNonConfigurationInstance

    public Object getLastNonConfigurationInstance() {
        return mLastNonConfigurationInstances != null
                ? mLastNonConfigurationInstances.activity : null;
    }

由于onRetainNonConfigurationInstance是final修饰的不可以重写,但是如果想在 Activity 中自定义想要恢复的数据,我们可以使用上述两个方法的内部方法

  • onRetainCustomNonConfigurationInstance()方法
    @Deprecated
    @Nullable
    public Object onRetainCustomNonConfigurationInstance() {
        return null;
    }

需要重写,重写后系统会帮我们调用,介于onStop和onDestory之间
在这里插入图片描述

  • getLastCustomNonConfigurationInstance()方法
    可以重写(一般不用重写),但是需要自行调用,只能在onCreate到onStart之间调用,超出范围如在onResume中调用则无效,获取不到任何东西
    @Deprecated
    @Nullable
    public Object getLastCustomNonConfigurationInstance() {
        NonConfigurationInstances nc = (NonConfigurationInstances)
                getLastNonConfigurationInstance();
        return nc != null ? nc.custom : null;
    }

简单使用:

  1. 重写onRetainCustomNonConfigurationInstance()

    @Nullable
    @Override
    public Object onRetainCustomNonConfigurationInstance() {
        nums = 10;
        Log.d("jian", "Activity onRetainCustomNonConfigurationInstance: ");
        //将数据分装成对象放进来
        return Integer.valueOf(nums);
    }
  1. 调用getLastCustomNonConfigurationInstance()
  • 可以在onStart() 中调用
    @Override
    protected void onStart() {
        super.onStart();
        Log.d("jian", "Activity onStart: ");
        Integer nums = (Integer)getLastCustomNonConfigurationInstance();
        Log.d("jian", "onStart: " + nums);
    }
  • 可以在onCreate()中调用,使用方法同上,记得强转类型
  • 注意在onResume()中调用的话拿到的是null

二.Fragment的生命周期详解

fragment的生命周期图( Activity 运行时)

在这里插入图片描述

Activity 生命周期对Fragment生命周期的影响图

在这里插入图片描述

简单演示:

  • 进入:
    在这里插入图片描述
  • 按下返回键
    在这里插入图片描述
    生命周期可自行演示,文章重点放在配置改变时的数据恢复上

fragment配置状态改变时数据恢复解决方案(如当旋转屏幕时):

onSaveInstanceState(@NonNull Bundle outState)

Fragment同样也提供了onSaveInstanceState方法介于onPause和onStop之间
在这里插入图片描述
不同的是:

  1. 无 **onRestoreInstanceState(@NonNull Bundle savedInstanceState)**方法
  2. 可以在onCreate, onCreateView, onActivityCreated中做数据恢复
    在这里插入图片描述
    使用方法跟Activity一样,不再演示

Fragment 的 setRetainInstance:

当配置发生改变时,Fragment 会随着宿主 Activity 销毁与重建,当我们调用 Fragment 中的 setRetainInstance(true) 方法时,系统允许 Fragment 绕开销毁-重建的过程。使用该方法,将会发送信号给系统,让 Activity 重建时,保留 Fragment 的实例。需要注意的是:

  • setRetainInstance(true) 一定要在 onSaveInstanceState方法被调用之前调用才有效,即在onPause中或者之前调用才有效
    在这里插入图片描述

  • 若在onSaveInstanceState中或者之后调用,则Fragment还是会销毁重建,从下图打印的log就可以知道重建后的实例跟销毁的实例不一样
    在这里插入图片描述

从上面的生命周期方法调用顺序可知

  • 调用setRetainInstance(true)后,不会调用 Fragment 的 onDestory() 方法,但仍然会调用 onDetach() 方法
  • 调用setRetainInstance(true)后,不会调用 Fragment 的 onCreate(Bundle) 方法。因为 Fragment 没有被重建。
  • 调用setRetainInstance(true)后,Fragment 的 onAttach(Activity) 与 onActivityCreated(Bundle) 方法仍然会被调用。

三.Activity和Fragment的生命周期调用顺序

  • 刚进入
    在这里插入图片描述

  • 按下Home键
    在这里插入图片描述

  • 按下Home键后重新进入
    在这里插入图片描述

  • 按下返回键
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/151610.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

笔记--Qt Pro语法总结

QT pro文件: 任何一个 Qt 项目都至少包含一个 pro 文件,此文件负责存储与当前项目有关的配置信息,比如: 项目中用到了哪些模块? 项目中包含哪些源文件,哪些头文件,它们的存储路径是什么&…

德育知识元素挖掘系统设计 软件工程 spring boot + Vue.js + python机器学习

第一章 绪论 摘要 当今社会发展迅速,机器学习相关技术快速在各行各业普及,制作数据挖掘系统的需求日益增长。同时,随着社会发展不断推进,对学生进行德育教育的规模越做越大,成为了教育行业发展的一大趋势。对于较大规模…

glibc 2.31 pwn——house of pig原题分析与示例程序

house of pig这种利用方式来源于XCTF 2021 final中的同名题,其原题使用的是libc 2.31版本,本文就根据这道题学习一下这种漏洞利用方式。 参考资料 这是一道C pwn,但漏洞本身与C不同于C的特性关系不大。 一共提供了5个选项: 增&…

idea无法安装插件

不能安装插件,首先需要确定是问题,最常见的是无法下载和安装不上, 1.无法下载解决版本 无法下载很多时候就是延迟太高导致的,我们先打开插件官网看一下 Python - IntelliJ IDEs Plugin | Marketplace 如果网站无法打开&#xf…

【测试】用例篇

努力经营当下,直至未来明朗! 文章目录一、设计测试用例的万能公式二、设计测试用例的具体方法1. 等价类2. 边界值3. 因果图(判定表)4. 场景设计法5. 正交法6. 错误猜测法:sparkles: 小结普通小孩也要热爱生活! 一、设…

JS数据类型判断的九种方式

JS 的数据类型检测是一道经典的八股文面试题。相信大家都能条件反射的回答出 4 种方法:typeof、constructor、instanceof 和 Object.prototype.toString,并且对它们各自的优缺点也是张口就来。 本文对这些方法做了简单归纳,同时又补充了其他…

Leetcode:112. 路径总和、113. 路径总和 II(C++)

目录 112. 路径总和: 问题描述: 实现代码与解析: 递归: 原理思路: 迭代: 原理思路: 113. 路径总和 II: 问题描述: 实现代码与解析: 迭代&#xff…

分享66个NET源码,总有一款适合您

NET源码 分享66个NET源码,总有一款适合您 NET源码下载链接:https://pan.baidu.com/s/1-H0UV3yly3p1PXbeLAvMtA?pwdk06f 提取码:k06f page_count 1 # 每个栏目开始业务content"text/html; charsetgb2312"base_url "http…

go defer return panic 执行顺序

根据代码实例运行结果来总结说明:定义一个函数,有多个defer (用于判断多个defer执行顺序),有panic和 return (判断与defer对比执行顺序)一、函数中有panicpackage mainimport "fmt"fu…

【矩阵论】8. 常用矩阵总结——秩1矩阵,优阵(单位正交阵),Hermite阵

矩阵论 1. 准备知识——复数域上矩阵,Hermite变换) 1.准备知识——复数域上的内积域正交阵 1.准备知识——Hermite阵,二次型,矩阵合同,正定阵,幂0阵,幂等阵,矩阵的秩 2. 矩阵分解——SVD准备知识——奇异值…

【性能调优】【离线任务】flink处理离线任务(8000个小文件?200多亿数据量?)稳定性与性能调优探索

文章目录一、场景描述1. 任务类型描述2. 问题任务二、相关理论1.Task Slots and Resources1.1. slots与资源的隔离和共享1.2 建议cpu和slot数关系2. tm的资源配置是否合适2.1. flink load problems2.2. 阿里 flink资源配置建议三、问题分析与解决1. 测试结果比对1.1. 任务11.2.…

小程序学习(2)-----常用的各类组件

新建项目 项目->新建项目-小程序,如下图所示 新建小程序页面 只需要在 app.json->pages 中新增页面的存放路径,小程序开发者工具可帮我们自动创建对应的页面文件,如图所示: 2.常用的视图容器类组件 ① view 普通视图区域类…

Java基础算法每日5道详解(3)

136. Single Number 单号 Given a non-empty array of integers nums, every element appears twice except for one. Find that single one. You must implement a solution with a linear runtime complexity and use only constant extra space. 给定一个非空整数数组 nu…

在Multisim导入TI提供的SPICE模型

对在multisim中导入TI模型的一个记录。 multisim中只有常规的元器件,对于很多元器件multisim都没有相应的模型,这就需要手动导入了。 Multisim导入模型1、从官网下载相应的模型文件2、在Multisim中导入模型3、写在后面1、从官网下载相应的模型文件 &…

c/c++ 函数(一) setw()、isdigit()、isalpha()、atoi()、itoa()

目录 1、setw(int n) <iomanip> 2、int isdigit(char ch) <ctype.h> 3、int isalpha(int c) <ctype.h> 4、int atoi(const char* str) <stdlib.h> 5、char* itoa(int num) <stdlib.h> 1、se…

Linux 基本权限

目录 1 shell命令以及运行原理 1.1 理解 1.2 意义 2 Linux权限的概念 2.1 概念 2.2 用户分类 2.3 Linux文件属性 2.4 Linux文件权限 2.4.1 文件访问者的分类&#xff08;人&#xff09; 2.4.2 root&&普通用户 vs 拥有者&&所属组&&other 2.4…

异步架构,避免相互依赖的系统耦合

前言&#xff1a; 使用缓存架构可以减少不必要的计算&#xff0c;快速响应用户请求&#xff0c;但是缓存只能改善系统的读操作性能&#xff0c;也就是在读取数据的时候&#xff0c;可以不从数据源中读取&#xff0c;而是通过缓存读取&#xff0c;以加速数据的读取速度。 但是…

vulnhub DC系列 DC-6

总结:wpscan爆破&#xff0c;nmap提权 下载地址 DC-6.zip (Size: 619 MB)Download: http://www.five86.com/downloads/DC-6.zipDownload (Mirror): https://download.vulnhub.com/dc/DC-6.zip使用方法:解压后&#xff0c;使用vm直接打开ova文件。 漏洞分析 信息收集 这里还是使…

4. 数据处理:用R语言实现【多路替换】真高效!!

b站课程视频链接&#xff1a; https://www.bilibili.com/video/BV19x411X7C6?p1 腾讯课堂(最新&#xff0c;但是要花钱&#xff0c;我花99&#x1f622;&#x1f622;元买了&#xff0c;感觉讲的没问题&#xff0c;就是知识点结构有点乱&#xff09;&#xff1a;https://ke.qq…

Linux中的vim最小集、指令集及其配置

目录 1. vim 最小集 2 vim指令集 2.1 命令模式的指令 2.1.1 插入模式 2.1.2 移动光标 2.1.3 删除文字 2.1.4 复制 2.1.5 替换 2.1.6 撤销 2.1.7 更改 2.1.8 跳至指定的行 2.1.9 shift ~:快速大小写切换 2.2 末行模式的指令 2.2.1 set nu/set nonu 2.2.2 vs file…