Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值

Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值

先看ComponentCallbacks2源代码中如何描述这些值的意义:

java 复制代码
package android.content
import android.annotation.IntDef; 
 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
 
/** 
扩展的ComponentCallbacks接口,增加了一个新的回调方法以实现更细粒度的内存管理。此接口可用于所有应用组件(包括android.app.Activity、 android.app.Service、 ContentProvider和 android.app.Application)。 
 
你应实现 onTrimMemory方法,根据当前系统限制逐步释放内存。使用此回调方法释放资源有助于提高系统的整体响应速度,同时也有助于提升用户体验,因为系统可以保持你的进程存活更长时间。即,
 如果你不根据此回调方法定义的内存级别来修剪资源,当你的进程在最近最少使用(LRU)列表中缓存时,系统更可能会终止你的进程,从而导致用户再次返回应用时需要重新启动和恢复所有状态。 
  
onTrimMemory方法提供的值并不代表内存限制的单一线性进程,而是为你提供有关内存可用性的不同类型线索: 
 
(A)当你的应用正在运行时: 
1、TRIM_MEMORY_RUNNING_MODERATE
设备内存开始不足。你的应用正在运行且不会被终止。 

2、TRIM_MEMORY_RUNNING_LOW
设备内存严重不足。你的应用正在运行且不会被终止,但请释放未使用的资源以提高系统性能(这将直接影响你应用的性能)。 

3、TRIM_MEMORY_RUNNING_CRITICAL
设备内存极度不足。你的应用进程尚不会被视为可终止进程,但如果应用不释放资源,系统将开始终止后台进程,因此你现在应该释放非关键资源,以防止性能下降。 

(B)当你的应用界面不可见时: 
1、TRIM_MEMORY_UI_HIDDEN
你的应用界面不再可见,因此现在是释放仅由界面使用的大型资源的好时机。 

(C)当你的应用进程位于后台LRU列表中时: 
1、TRIM_MEMORY_BACKGROUND
系统内存不足,且你的进程接近LRU列表的开头。虽然你的应用进程被终止的风险不高,但系统可能已经开始终止LRU列表中的进程,因此你应释放容易恢复的资源,以便你的进程保留在列表中,并在用户返回你的应用时快速恢复。 

2、TRIM_MEMORY_MODERATE
系统内存不足,且你的进程位于LRU列表的中间位置。如果系统内存进一步受限,你的进程有可能会被终止。 

3、TRIM_MEMORY_COMPLETE
系统内存不足,且如果你的进程现在不被回收内存,那么当系统需要回收内存时,你的进程将是首批被终止的进程之一。你应释放所有非关键资源,以便恢复应用状态。 
注意:为了支持低于API级别14的设备,你可以使用onLowMemory方法作为大致相当于 ComponentCallbacks2 TRIM_MEMORY_COMPLETE 级别的回退方法。 
当系统开始终止LRU列表中的进程时,虽然它主要自下而上进行工作,但也会考虑哪些进程消耗的内存更多,因此终止这些进程可以获得更多的内存。因此,当你的进程在LRU列表中时,整体消耗的内存越少,保留在列表中的机会就越大,也就能在用户返回时更快恢复。

有关进程生命周期不同阶段(例如,进程被放入后台LRU列表的含义)的更多信息,请参阅进程和线程文档。 
 */ 
public interface ComponentCallbacks2 extends ComponentCallbacks { 
 
/** @hide */ 
 @IntDef(prefix = { "TRIM_MEMORY_" }, value = { 
 TRIM_MEMORY_COMPLETE, 
 TRIM_MEMORY_MODERATE, 
 TRIM_MEMORY_BACKGROUND, 
 TRIM_MEMORY_UI_HIDDEN, 
 TRIM_MEMORY_RUNNING_CRITICAL, 
 TRIM_MEMORY_RUNNING_LOW, 
 TRIM_MEMORY_RUNNING_MODERATE, 
 }) 
 @Retention(RetentionPolicy.SOURCE) 
 public @interface TrimMemoryLevel {} 
 
/** 
 onTrimMemory(int)的级别:进程已接近后台LRU列表的末尾,如果很快找不到更多内存,它将被终止。 
 
 @deprecated 从API级别34开始,应用将不会收到此级别的通知。 
 */ 
 @Deprecated 
 static final int TRIM_MEMORY_COMPLETE = 80; 
 
/** 
onTrimMemory(int)的级别:进程在后台LRU列表的中间位置;释放内存可以帮助系统稍后保持列表中其他进程的运行,从而提高整体性能。 
 
 @deprecated 从API级别34开始,应用将不会收到此级别的通知。 
 */ 
 @Deprecated 
 static final int TRIM_MEMORY_MODERATE = 60; 
 
/** 
onTrimMemory(int)的级别:进程已进入LRU列表。这是清理资源的好机会,这些资源可以在用户返回应用时高效且快速地重新构建。 
*/ 
 static final int TRIM_MEMORY_BACKGROUND = 40; 
 
/** 
onTrimMemory(int)的级别:进程之前一直在显示用户界面,但现在不再显示。此时应释放与界面相关的大型分配,以便更好地管理内存。 
*/ 
 static final int TRIM_MEMORY_UI_HIDDEN = 20; 
 
/** 
onTrimMemory(int)的级别:进程不是可有可无的后台进程,但设备运行内存极度不足,很快将无法保持任何后台进程运行。你的运行进程应释放尽可能多的非关键资源,以便在其他地方使用这些内存。接下来会发生的事情是调用onLowMemory(),报告后台无法保留任何内容,这种情况可能会开始明显影响用户。 
 
@deprecated 从API级别34开始,应用将不会收到此级别的通知。 
*/ 
 @Deprecated 
 static final int TRIM_MEMORY_RUNNING_CRITICAL = 15; 
 
/** 
onTrimMemory(int)的级别:进程不是可有可无的后台进程,但设备运行内存不足。你的运行进程应释放不再需要的资源,以便在其他地方使用这些内存。 
 
@deprecated 从API级别34开始,应用将不会收到此级别的通知。 
 */ 
 @Deprecated 
 static final int TRIM_MEMORY_RUNNING_LOW = 10; 
 
 /** 
onTrimMemory(int)的级别:进程不是可有可无的后台进程,但设备运行内存略显不足。你的运行进程可能希望释放一些不再需要的资源以供其他进程使用。 

@deprecated 从API级别34开始,应用将不会收到此级别的通知。 
 */ 
 @Deprecated 
 static final int TRIM_MEMORY_RUNNING_MODERATE = 5; 
 
 /** 
当操作系统确定进程可以修剪其进程中不需要的内存时调用。
 
你永远不应与级别的确切值进行比较,因为可能会添加新的中间值------你通常希望比较该值是否大于或等于你感兴趣的级别。 

要在任何时间点检索进程的当前修剪级别,你可以使用 android.app.ActivityManager#getMyMemoryState 
 ActivityManager.getMyMemoryState(RunningAppProcessInfo)}。 
 
 @param level 修剪的上下文,提示应用程序可能希望执行的修剪量。 
 */ 
 void onTrimMemory(@TrimMemoryLevel int level); 
}

特别需要关注的有两部分:

(1)其中不少level值已经在Android新版,尤其是Android API 34后失效。在Android API 34后,目前只有两个level值:

40TRIM_MEMORY_BACKGROUND

20TRIM_MEMORY_UI_HIDDEN

有效,其他的level值Android已经废弃不用,关于40和20:

java 复制代码
    /**
     * Level for {@link #onTrimMemory(int)}: the process has gone on to the
     * LRU list.  This is a good opportunity to clean up resources that can
     * efficiently and quickly be re-built if the user returns to the app.
     */
    static final int TRIM_MEMORY_BACKGROUND = 40;
    
    /**
     * Level for {@link #onTrimMemory(int)}: the process had been showing
     * a user interface, and is no longer doing so.  Large allocations with
     * the UI should be released at this point to allow memory to be better
     * managed.
     */
    static final int TRIM_MEMORY_UI_HIDDEN = 20;

(2)不要寄希望于判断 level 值与某个内存水位线境界值精准匹配,而是要判断level值是否大于等于某个警戒水位线值。Android源代码中是这么说的:

You should never compare to exact values of the level, since new intermediate values may be added -- you will typically want to compare if the value is greater or equal to a level you are interested in.

你永远不应与级别的确切值进行比较,因为可能会添加新的中间值------你通常希望比较该值是否大于或等于你感兴趣的级别。

比如,经典开源框架Glide在trimMemory(int level)时,依赖关键的40( level ≥ TRIM_MEMORY_BACKGROUND)和20( level ≥ TRIM_MEMORY_UI_HIDDEN)做内存裁剪:

java 复制代码
  @Override
  public void trimMemory(int level) {
    if (level >= android.content.ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
      // Entering list of cached background apps
      // Evict our entire bitmap cache
      clearMemory();
    } else if (level >= android.content.ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
        || level == android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) {
      // The app's UI is no longer visible, or app is in the foreground but system is running
      // critically low on memory
      // Evict oldest half of our bitmap cache
      trimToSize(getMaxSize() / 2);
    }
  }

Android之Application的onTerminate能监听应用退出吗?-CSDN博客文章浏览阅读3w次,点赞8次,收藏9次。 Android之Application的onTerminate能监听应用退出吗?一些Android开发者在不经意间发现Android的Application中有一个公开的回调方法:onTerminate()继而想当然的认为该方法即是Android的整个App应用退出后的回调,因为Terminate的词面意思就是..._onterminatehttps://blog.csdn.net/zhangphil/article/details/81232302

相关推荐
来来走走1 小时前
Flutter开发 网络请求
android·flutter
独行soc8 小时前
2025年渗透测试面试题总结-18(题目+回答)
android·python·科技·面试·职场和发展·渗透测试
雨白8 小时前
登录和授权:Cookie与Authorization Header机制详解
android
Frank_HarmonyOS9 小时前
【Android -- 多线程】Handler 消息机制
android
一条上岸小咸鱼10 小时前
Kotlin 基本数据类型(一):概述及分类
android·kotlin
没盐水菠萝10 小时前
Android - 动态切换桌面图标
android
AI 嗯啦10 小时前
SQL详细语法教程(三)mysql的函数知识
android·开发语言·数据库·python·sql·mysql
跨界混迹车辆网的Android工程师12 小时前
adb 发送广播
android
超勇的阿杰14 小时前
gulimall项目笔记:P54三级分类拖拽功能实现
android·笔记
峥嵘life15 小时前
Android 欧盟网络安全EN18031 要求对应的基本表格填写
android·安全·web安全