Android内存优化之OnTrimMemory简介

embedded/2024/10/25 10:29:28/

Android内存优化之OnTrimMemory简介

  • 一、前言
  • 二、 API 介绍
    • 2.1、哪些组件可以实现OnTrimMemory回调
    • 2.2、level参数的含义
      • 2.2.1、应用正在运行时:
      • 2.2.2、应用的可见性发生变化时:
      • 2.2.3、应用的进程位于后台 LRU 列表中时:
    • 3、示例代码
  • 三、拓展阅读
    • 3.1、有哪些典型的使用场景
      • 3.1.1、常驻内存的应用
      • 3.1.2、有后台Service运行的应用
    • 3.2、为什么要调用OnTrimMemory
    • 3.3、OnTrimMemory的TRIM_MEMORY_UI_HIDDEN回调和onStop的关系
    • 3.4、OnTrimMemory和OnLowMemory的关系
  • 四、附录

一、前言

在Android开发中,内存管理是一个至关重要的课题。特别是在系统内存紧张时,如何有效地释放资源以避免应用被系统杀死,是每个开发者需要考虑的问题。其中,OnTrimMemory 回调是 Android 4.0 之后提供的一个API,这个 API 是提供给开发者的,它的主要作用是提示开发者在系统内存不足的时候,通过处理部分资源来释放内存,从而避免被 Android 系统杀死。

二、 API 介绍

2.1、哪些组件可以实现OnTrimMemory回调

Application.onTrimMemory()
Activity.onTrimMemory()
Fragement.OnTrimMemory()
Service.onTrimMemory()
ContentProvider.OnTrimMemory()

2.2、level参数的含义

可根据应用的当前所处的状态氛围以下三种情况:

2.2.1、应用正在运行时:

TRIM_MEMORY_RUNNING_MODERATE 设备开始内存不足。应用正在运行且不可杀。
TRIM_MEMORY_RUNNING_LOW 设备内存严重不足。应用正在运行且不可杀,但请释放未使用的资源以提高系统性能(这直接影响您的应用性能)。
TRIM_MEMORY_RUNNING_CRITICAL 设备内存极度不足。应用尚未被视为可杀进程,但如果应用不释放资源,系统将开始杀后台进程,因此现在应释放非关键资源以防止性能下降。

2.2.2、应用的可见性发生变化时:

TRIM_MEMORY_UI_HIDDEN 应用的用户界面不再可见,所以这是释放仅由用户界面使用的大型资源的好时机。

2.2.3、应用的进程位于后台 LRU 列表中时:

TRIM_MEMORY_BACKGROUND 系统内存不足,进程接近 LRU 列表的开头。虽然应用进程被杀的风险不高,但系统可能已经在杀 LRU 列表中的进程,因此应释放易于恢复的资源,以便进程留在列表中,并在用户返回应用时快速恢复。
TRIM_MEMORY_MODERATE 系统内存不足,应用进程接近 LRU 列表的中间。如果系统内存进一步受限,进程有可能被杀死。
TRIM_MEMORY_COMPLETE 系统内存不足,如果系统现在不恢复内存,该应用进程将是首批被杀死的进程之一。

3、示例代码

以下是官方提供的示例代码

import android.content.ComponentCallbacks2class MainActivity : AppCompatActivity(), ComponentCallbacks2 {/*** 当用户界面隐藏或系统资源变低时释放内存。* @param level 所引发的与内存相关的事件*/override fun onTrimMemory(level: Int) {// 确定引发了哪个生命周期或系统事件。when (level) {ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN -> {// 释放当前占用内存的任何 UI 对象。用户界面移至后台。}ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE,ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW,ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL -> {/*释放您的应用程序运行时不需要的任何内存。应用程序运行时设备内存不足。引发的事件表明与内存相关事件的严重程度。如果事件是 TRIM_MEMORY_RUNNING_CRITICAL,则系统开始停止后台进程。*/}ComponentCallbacks2.TRIM_MEMORY_BACKGROUND,ComponentCallbacks2.TRIM_MEMORY_MODERATE,ComponentCallbacks2.TRIM_MEMORY_COMPLETE -> {/*尽可能多地释放进程的内存。该应用在 LRU 列表中,并且系统内存不足。引发的事件表明该应用在 LRU 列表中的位置。如果事件是 TRIM_MEMORY_COMPLETE,则该进程是首先被终止的进程之一。 */}else -> {/*释放任何非关键的数据结构。 该应用从系统接收到一个无法识别的内存级别值。将此视为通用的低内存消息。 */}}}
}

三、拓展阅读

3.1、有哪些典型的使用场景

3.1.1、常驻内存的应用

一些常驻内存的应用,比如Launcher、安全中心、电话等,在用户使用过要退出的时候,需要调用OnTrimMemory来及时释放用户使用的时候所产生的多余的内存资源:比如动态生成的View、图片缓存、Fragment等。

3.1.2、有后台Service运行的应用

这些应用不是常驻内存的,意味着可以被任务管理器杀掉,但是在某些场景下用户不会去杀。这类应用包括:音乐、下载等。用户退出UI界面后,音乐还在继续播放,下载程序还在运行。这时候音乐应该释放部分UI资源和Cache.

3.2、为什么要调用OnTrimMemory

尽管系统在内存不足的时候杀进程的顺序是按照LRU Cache中从低到高来的,但是它同时也会考虑杀掉那些占用内存较高的应用来让系统更快地获得更多的内存。所以如果你的应用占用内存较小,就可以增加不被杀掉的几率,从而快速地恢复(如果不被杀掉,启动的时候就是热启动,否则就是冷启动,其速度差在2~3倍)。所以说在几个不同的OnTrimMemory回调中释放自己的UI资源,可以有效地提高用户体验。

3.3、OnTrimMemory的TRIM_MEMORY_UI_HIDDEN回调和onStop的关系

1、直接按Home键回到桌面onTrimMemory的TRIM_MEMORY_UI_HIDDEN 回调是在是onStop方法之前调用的

2、应用间切换onTrimMemory的TRIM_MEMORY_UI_HIDDEN 回调是在是onStop方法之后调用的
以上结论结论经过demo验证,大家有兴趣也可以写个demo试试看。

onTrimMemory()的TRIM_MEMORY_UI_HIDDEN回调只有当我们程序中的所有UI组件全部不可见的时候才会触发,这和onStop()方法还是有很大区别的,因为onStop()方法只是当一个Activity完全不可见的时候就会调用,比如说用户打开了我们程序中的另一个Activity。

因此,我们可以在onStop()方法中去释放一些Activity相关的资源,比如说取消网络连接或者注销广播接收器等,但是像UI相关的资源应该一直要等到onTrimMemory(TRIM_MEMORY_UI_HIDDEN)这个回调之后才去释放,这样可以保证如果用户只是从我们程序的一个Activity回到了另外一个Activity,界面相关的资源都不需要重新加载,从而提升响应速度。

3.4、OnTrimMemory和OnLowMemory的关系

在引入OnTrimMemory之前都是使用OnLowMemory回调,需要知道的是,OnLowMemory大概和 OnTrimMemory中的TRIM_MEMORY_COMPLETE级别相同,如果你想兼容api<14的机器,那么可以用 OnLowMemory来实现,否则你可以忽略OnLowMemory,直接使用OnTrimMemory即可。 现在国内api<14以下的设备基本不存在了, 大家基本可以忽略。

四、附录

Android官方文档-管理应用内存
ComponentCallbacks2官方API
从OnTrimMemory角度谈Android代码内存优化


http://www.ppmy.cn/embedded/97984.html

相关文章

C++入门——19C++的类型转换

1.C语言的类型转换 C语言中总共有两种形式的类型转换&#xff1a;隐式类型转换和显式类型转换。 1. 隐式类型转化&#xff1a;编译器在编译阶段自动进行&#xff0c;能转就转&#xff0c;不能转就编译失败 2. 显式类型转化&#xff1a;需要用户自己处理 oid Test () {int i …

每天一个数据分析题(四百八十三)- 统计推断

关于统计推断的内容&#xff0c;样本均值对总体均值的估计&#xff0c;满足下面哪些评价标准&#xff1f; A. 无偏性 B. 有效性 C. 一致性 D. 以上皆不是 数据分析认证考试介绍&#xff1a;点击进入 题目来源于CDA模拟题库 点击此处获取答案 数据分析专项练习题库 内容…

正点原子linux开发板 qt程序交叉编译执行

1.开发板光盘 A-基础资料->5、开发工具->1、交叉编译器->fsl-imx-x11-glibc-x86_64-meta-toolchain-qt5-cortexa7hf-neon-toolchain-4.1.15-2.1.0.sh 拷贝到 Ubuntu 虚拟机 用文件传输系统或者共享文件夹传输到linux虚拟机 用ls -l查看权限&#xff0c;如果是白色的使…

4. 数据结构——队列的操作实现

队列操作实现&#xff1a;循环队列和链队列的初始化、求长度、出队、入队、去队头元素等操作。 1. 循环队列 这里通过浪费一个空间来区别队满和队空。 ❗注意&#xff1a;rear和front的指针循环加操作、队满的判断、队空的判断&#xff0c;求队长。&#xff08;因为是循环队…

Python爬虫技术与K-means算法的计算机类招聘信息获取与数据分析

有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主 目录 摘要.... 1 Abstract 2 1 引言.... 3 1.1 研究背景... 3 1.2 国内外研究现状... 4 1.3 研究目的... 5 1.4 研究意义... 7 2 关键技术理论介绍... 7 2.1 Python爬虫... 7 2.1 K-means…

金贝E-KA1M 5.5T卓越性能,引领行业新高度

金贝 E-KA1M 5.5t 主要适用于家庭、书房、办公室等对噪音有一定要求的环境。它在运行时噪音极低&#xff0c;不会打扰您的日常生活&#xff0c;无论是放在家中还是办公场所&#xff0c;都能悄然为您创造财富。 金贝 E-KA1M 5.5t是一款具有较强算力的静音挖kuang机&#xff0c;其…

SQLite 插入数据并返回自增ID

要插入数据并返回自增ID&#xff0c;我们可以使用SQLite的last_insert_rowid()函数。这个函数返回了最后一次插入操作的自增ID。 下面我们通过一个示例来演示如何插入数据并返回自增ID。 首先&#xff0c;创建一个表来存储学生信息&#xff1a; CREATE TABLE students (id I…

Django ORM使用

1.基本操作 1.1 添加 (1)save() 通过创建模型类对象,执行对象的save()方法保存到数据库中。 student = Student(name="测试",age=17,sex=True ) student.save() # 保存 print(student.id) # 判断是否新增有ID (2)create() 通过模型类.objects.create()保存…