安卓源码分析(10)Lifecycle实现组件生命周期管理
参考:
https://developer.android.google.cn/topic/libraries/architecture/lifecycle?hl=zh-cn#java
https://developer.android.google.cn/reference/androidx/lifecycle/Lifecycle
文章目录
- 1、概述
- 2、LifeCycle类
- 3、LifecycleOwner类
- 4、LifecycleObserver类
1、概述
Android Lifecycle 是一种用于管理 Android 组件(如 Activity 和 Fragment)生命周期的架构组件。Lifecycle 提供了一种在组件生命周期变化时触发相应操作的方式,以帮助开发者编写更加健壮和可维护的代码。
Android 组件的生命周期包括多个阶段,如创建(Create)、启动(Start)、恢复(Resume)、暂停(Pause)、停止(Stop)和销毁(Destroy)。在每个阶段,组件可以执行特定的操作,如初始化界面、加载数据、保存状态等。例如,经典的Activity组件的生命周期图:

使用 Lifecycle 可以将与组件生命周期相关的操作集中到一个地方,并确保这些操作在正确的时机被调用。说白了,就是将生命周期的管理和业务实现分离,抽象成通用的公共组件,以实现代码复用和抽象。
在 Android 框架中定义的大多数应用组件都存在生命周期。生命周期由操作系统或进程中运行的框架代码管理。它们是 Android 工作原理的核心,应用必须遵循它们。如果不这样做,可能会引发内存泄漏甚至应用崩溃。
Lifecycle 提供了以下主要的元素和功能:
- LifecycleOwner: 一个实现了 LifecycleOwner 接口的对象,通常是 Activity 或 Fragment。它负责提供生命周期的状态。
- Lifecycle : 表示一个组件的生命周期状态,如 CREATED、STARTED、RESUMED 等。可以通过 Lifecycle 对象来观察和监听生命周期状态的变化。
- LifecycleObserver: 一个实现了 LifecycleObserver 接口的类,用于观察和响应生命周期事件。
通过使用 Lifecycle,开发者可以避免常见的生命周期相关问题,如内存泄漏、UI 更新异常、数据不一致等。它提供了一种结构化的方式来管理生命周期,并使代码更易于理解、测试和维护。
总之,Android Lifecycle 是一种用于管理 Android 组件生命周期的架构组件,它提供了一套机制和工具来观察、响应和管理组件的状态变化,使开发者能够编写更加可靠和健壮的代码。
2、LifeCycle类
Lifecycle 是一个类,用于存储有关组件(如 activity 或 fragment)的生命周期状态的信息,并允许其他对象观测此状态。
Lifecycle 使用两种主要枚举跟踪其关联组件的生命周期状态:
事件
从框架和 Lifecycle 类分派的生命周期事件。这些事件映射到 activity 和 fragment 中的回调事件。
状态
Lifecycle 对象所跟踪的组件的当前状态。
跟踪生命周期的流程如下:

熟悉状态机的同学很容易理解,状态在发生某些事情时就会跃迁到另一个状态,上图的箭头就描述了某些事件发生时状态的跃迁。
LifeCycle定义了以下几种状态:
public enum State {/*** Destroyed state for a LifecycleOwner. After this event, this Lifecycle will not dispatch* any more events. For instance, for an {@link android.app.Activity}, this state is reached* <b>right before</b> Activity's {@link android.app.Activity#onDestroy() onDestroy} call.*/DESTROYED,/*** Initialized state for a LifecycleOwner. For an {@link android.app.Activity}, this is* the state when it is constructed but has not received* {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} yet.*/INITIALIZED,/*** Created state for a LifecycleOwner. For an {@link android.app.Activity}, this state* is reached in two cases:* <ul>* <li>after {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} call;* <li><b>right before</b> {@link android.app.Activity#onStop() onStop} call.* </ul>*/CREATED,/*** Started state for a LifecycleOwner. For an {@link android.app.Activity}, this state* is reached in two cases:* <ul>* <li>after {@link android.app.Activity#onStart() onStart} call;* <li><b>right before</b> {@link android.app.Activity#onPause() onPause} call.* </ul>*/STARTED,/*** Resumed state for a LifecycleOwner. For an {@link android.app.Activity}, this state* is reached after {@link android.app.Activity#onResume() onResume} is called.*/RESUMED;/*** Compares if this State is greater or equal to the given {@code state}.** @param state State to compare with* @return true if this State is greater or equal to the given {@code state}*/public boolean isAtLeast(@NonNull State state) {return compareTo(state) >= 0;}}
定义的事件如下:
public enum Event {/*** Constant for onCreate event of the {@link LifecycleOwner}.*/ON_CREATE,/*** Constant for onStart event of the {@link LifecycleOwner}.*/ON_START,/*** Constant for onResume event of the {@link LifecycleOwner}.*/ON_RESUME,/*** Constant for onPause event of the {@link LifecycleOwner}.*/ON_PAUSE,/*** Constant for onStop event of the {@link LifecycleOwner}.*/ON_STOP,/*** Constant for onDestroy event of the {@link LifecycleOwner}.*/ON_DESTROY,/*** An {@link Event Event} constant that can be used to match all events.*/ON_ANY;
LifeCycle除了提供了生命周期的记录,还提供了观测的方法,采用了设计模式观察者模式,
/*** Adds a LifecycleObserver that will be notified when the LifecycleOwner changes* state.* <p>* The given observer will be brought to the current state of the LifecycleOwner.* For example, if the LifecycleOwner is in {@link State#STARTED} state, the given observer* will receive {@link Event#ON_CREATE}, {@link Event#ON_START} events.** @param observer The observer to notify.*/@MainThreadpublic abstract void addObserver(@NonNull LifecycleObserver observer);/*** Removes the given observer from the observers list.* <p>* If this method is called while a state change is being dispatched,* <ul>* <li>If the given observer has not yet received that event, it will not receive it.* <li>If the given observer has more than 1 method that observes the currently dispatched* event and at least one of them received the event, all of them will receive the event and* the removal will happen afterwards.* </ul>** @param observer The observer to be removed.*/@MainThreadpublic abstract void removeObserver(@NonNull LifecycleObserver observer);
想要观测该状态,需要被Lifecycle添加为观察者,当然也可以移除解除通知。
同时提供了一个供外部查询当前状态的接口:
/*** Returns the current state of the Lifecycle.** @return The current state of the Lifecycle.*/@MainThread@NonNullpublic abstract State getCurrentState();
3、LifecycleOwner类
LifecycleOwner只是个简单的接口类,定义了一个获取Lifecycle的方法。
public interface LifecycleOwner {/*** Returns the Lifecycle of the provider.** @return The lifecycle of the provider.*/@NonNullLifecycle getLifecycle();
}
想要拥有生命周期管理的组件只要实现该接口即可。
像ComponentActivity就继承于该接口。
4、LifecycleObserver类
Lifecycle是一个被观测对象,自然要有观察者,即关心生命周期变化的人。提供了LifecycleObserver 类用于观测Lifecycle,学java的都知道,java就喜欢极度抽象,LifecycleObserver 是个空接口类,啥都没有。
public interface LifecycleObserver {}
观察者的接口自然是观测Lifecyle状态变化,onXXX习惯用于表达XXX事件发生时的回调。
表达事件/状态变化可以有两种表达方式,一种是穷举出所有的事件,一种是通过形参表达,android两种形式都提供了:
FullLifecycleObserver 穷举定义了所有事件回调:
interface FullLifecycleObserver extends LifecycleObserver {void onCreate(LifecycleOwner owner);void onStart(LifecycleOwner owner);void onResume(LifecycleOwner owner);void onPause(LifecycleOwner owner);void onStop(LifecycleOwner owner);void onDestroy(LifecycleOwner owner);
}
通过函数形参区分不同事件的接口定义LifecycleEventObserver :
/*** Class that can receive any lifecycle change and dispatch it to the receiver.* <p>* If a class implements both this interface and* {@link androidx.lifecycle.DefaultLifecycleObserver}, then* methods of {@code DefaultLifecycleObserver} will be called first, and then followed by the call* of {@link LifecycleEventObserver#onStateChanged(LifecycleOwner, Lifecycle.Event)}* <p>* If a class implements this interface and in the same time uses {@link OnLifecycleEvent}, then* annotations will be ignored.*/
public interface LifecycleEventObserver extends LifecycleObserver {/*** Called when a state transition event happens.** @param source The source of the event* @param event The event*/void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event);
}
注释里提到,如果一个Observer同时实现了这两种形式的接口,FullLifecycleObserver的相应接口会先被调用,其次才是onStateChanged这个接口。
同时还定义了一个空实现的DefaultLifecycleObserver,这样我们可以根据需要,override部分接口。
在最后,我们补全一张类图:
相关文章:
安卓源码分析(10)Lifecycle实现组件生命周期管理
参考: https://developer.android.google.cn/topic/libraries/architecture/lifecycle?hlzh-cn#java https://developer.android.google.cn/reference/androidx/lifecycle/Lifecycle 文章目录 1、概述2、LifeCycle类3、LifecycleOwner类4、LifecycleObserver类 1、…...
IP 多播协议(IP Multicast Protocol)
IP 多播协议(IP Multicast Protocol)是一种在网络中一对多传输数据的通信方式。在传统的单播通信中,数据从一个发送方发送到一个接收方;而在多播通信中,数据可以从一个发送方传输到多个接收方,从而有效地节…...
Jmeter 配置环境变量,简明教程专享
通过给 JMeter 配置环境变量,可以快捷的打开 JMeter: 打开终端。执行 jmeter。 配置环境变量的方法如下。 Mac 和 Linux 系统 在 ~/.bashrc 中加如下内容: export JMETER_HOMEJMeter所在目录 export PATH$JAVA_HOME/bin:$PATH:.:$JMETER…...
WebService—XFire配置笔记
在学习之前,一直以为WebService就是一个工具,在两个服务器之间建立一个通信,帮我们把需要传输的数据组织成规范的XML数据并发送到目的地,实际情况也确实是这样的,不过更高级一点的是,XFire不但可以帮我们生成XML发送,而且可以在接收了xml之后还可以直接返回对象给我们用…...
【LangChain学习】基于PDF文档构建问答知识库(一)前期准备
这系列主要介绍如何使用LangChain大模型,结合ChatGPT3.5,基于PDF文档构建专属的问答知识库。 一、 环境搭建 LangChain 和 OpenAI 本身可支持 Nodejs 和 Python 两个版本,笔者后续的介绍主要用到Python版本,如果有需要Nodejs版本…...
Word(1):文章页码设置
1.需求 在文档的封皮页不设置页码,在目录页页码设置为罗马数字,在正文使用阿拉伯数字。 2.解决方法 step1: 在封皮页的最后,点击”插入“-分隔符-分节符(下一页) step2:在目录页的最后&…...
Linux MQTT智能家居(温度,湿度,环境监测,摄像头等界面布局设置)
文章目录 前言一、温度湿度曲线布局二、环境监测界面布局三、摄像头界面布局总结 前言 本篇文章来完成另外三个界面的布局设置。 这里会使用到 feiyangqingyun的一些控件库。 一、温度湿度曲线布局 TempHumtiy.h: #ifndef TEMPHUMTIY_H #define TEMPHUMTIY_H#include <…...
权衡与选择:如何巧妙管理项目需求的优先级
在项目管理领域,处理和管理需求可能是最具挑战性的环节之一。每一个项目都充满了各种需求,从业务需求到技术需求,从用户需求到系统需求。而如何有效地为这些需求排列优先级,不仅会影响项目的进度和资源分配,还会直接关…...
UGUI组件EventTrigger用法
一.Unity编辑器中EventTrigger组件用法 1.添加事件类型 2.绑定gameObject指定组件的方法 3.方法执行逻辑 public class NewBehaviourScript : MonoBehaviour {public void PointerDown(){Debug.Log("Trigger PointerDown");} } 4.按下鼠标,绑定方法成功…...
Visual Studio 2019 详细安装教程(图文版)
前言 Visual Studio 2019 安装包的下载教程、安装教程 教程 博主博客链接:https://blog.csdn.net/m0_74014525 关注博主,后期持续更新系列文章 ********文章附有百度网盘安装包链接********* 系列文章 第一篇:Visual Studio 2019 详细安装教…...
idea添加作者信息
idea添加作者信息 自定义作者信息idea添加作者信息自定义作者信息 自定义作者信息 idea添加作者信息 在idea中,经常会有这些波浪纹提示,放在上面之后会提示添加作者信息,点击添加作者信息后,但是不是自己想要的 这里提取的话好像没什么办法…...
后端开发6.权限控制模块
概述 权限控制采用springsecurity 数据库设计 用户表 DROP TABLE IF EXISTS `admin`; CREATE TABLE `admin` (`aid` int(32) NOT NULL AUTO_INCREMENT,`email` varchar(50) DEFAULT NULL,`username` varchar(50) DEFAULT NULL,`password` varchar(255) DEFAULT NULL,`phone…...
Golang原生实现JA3指纹修改,并支持Proxy代理
起因 抓取某个HTTPS网站的时候 开启charles代理能够抓取成功,关闭被风控 通过检测,怀疑可能是tls的时候有区别 尝试 golang的http中,Transport.TLSClientConfig是可以自定义设置的 但起初通过随意设置并不能绕过风控 困难 使用golang的http客户端,修改DialTLSContext函数的…...
一个案例:Vue2组件化开发组件从入门到入土
1. 环境搭建 1.1. 创建项目 npm install -g vue/clivue create vue_study_todolist1.2. 清空项目代码 清楚HelloWorld.Vue代码中的内容。 1.3. 启动空项目 1.4 项目目标 项目组件实现以下效果 2. 组件拆分代码 Vue是一个基于组件的框架,允许您将界面拆分成小的…...
智慧工地源码 智慧工地云平台源码 智慧工地APP源码
智慧工地的核心是数字化,它通过传感器、监控设备、智能终端等技术手段,实现对工地各个环节的实时数据采集和传输,如环境温度、湿度、噪音等数据信息,将数据汇集到云端进行处理和分析,生成各种报表、图表和预警信息&…...
考研408 | 【计算机网络】 网络层
导图 网络层: 路由器功能:转发&路由选择 数据平面 数据平面执行的主要功能是根据转发表进行转发,这是路由器的本地动作。 控制平面 1.传统方法/每路由器法: 2.SDN方法(Software-Defined Networking) 控制平面中的…...
postgresql|数据库|角色(用户)管理工作---授权和去权以及usage和select两种权限的区别
前言: postgresql做为一个比较复杂的关系型的重型数据库,不管是安装部署,还是后期的运行维护,都还是有比较多的细节问题需要引起关注。 例如,用户权限的合理分配,那么,什么是权限的合理分配呢…...
【题解】旋转数组的最小数字、比较版本号
文章目录 旋转数组的最小数字比较版本号 旋转数组的最小数字 题目链接:旋转数组的最小数字 解题思路1:遍历求最小值 代码如下: int minNumberInRotateArray(vector<int> rotateArray) {int min rotateArray[0];for(auto const&…...
springboot系统内多级调用报错日志输出顺序
忘记,模糊,故专门验证下 比如方法1调用方法2 方法2又调用方法3 方法3报错 那么报错日志中哪个方法所在行先打印出来? 直接上测试代码 package pers.wwz.study.exception.controller;import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.Requ…...
django——配置 settings.py 及相关参数说明
3. 配置 settings.py 及相关参数说明 3.1 配置setting.py文件 设置setting.py文件 加入安装的库 apps.erp_test, rest_framework, django_filters, drf_spectacular,加入新增的APP users启动项目 # 运行项目先执行数据库相关操作,再启动 django 项目 python manag…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
