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

相关推荐
Dnelic-8 小时前
Android 5G NR 状态类型介绍
android·5g·telephony·connectivity·自学笔记·移动网络数据
吗喽对你问好10 小时前
Android UI 控件详解实践
android·ui
东风西巷13 小时前
X-plore File Manager v4.34.02 修改版:安卓设备上的全能文件管理器
android·网络·软件需求
yzpyzp13 小时前
Android 15中的16KB大页有何优势?
android
安卓开发者13 小时前
Android Room 持久化库:简化数据库操作
android·数据库
程序视点13 小时前
FadCam安卓后台录制神器:2025最全使用指南(开源/免费/息屏录制)
android
猿小蔡14 小时前
Android ADB命令之内存统计与分析
android
游戏开发爱好者815 小时前
没有 Mac,如何上架 iOS App?多项目复用与流程标准化实战分享
android·ios·小程序·https·uni-app·iphone·webview
你过来啊你16 小时前
Android开发中nfc协议分析
android
Auspemak-Derafru17 小时前
安卓上的迷之K_1171477665
android