Android可以通过多种方式从您的应用程序中回收内存,或者在必要时将应用程序彻底关闭以释放内存以用于关键任务。为了进一步帮助平衡系统内存,避免系统需要终止应用程序进程,可以在Activity
类中实现ComponentCallbacks2
接口提供的onTrimMemory()
回调方法,从而允许您的应用程序在处于前台或后台时侦听与内存相关的事件,然后释放对象以响应应用程序生命周期,或者指示系统需要回收内存的系统事件。
例如,您可以实现onTrimMemory()
回调以响应不同的内存相关事件,如下所示
import android.content.ComponentCallbacks2;
// Other import statements …
public class MainActivity extends AppCompatActivity
implements ComponentCallbacks2 {
// Other activity code …
/**
-
Release memory when the UI becomes hidden or when system resources become low.
-
@param level the memory-related event that was raised.
*/
public void onTrimMemory(int level) {
// Determine which lifecycle or system event was raised.
switch (level) {
case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
/*
Release any UI objects that currently hold memory.
The user interface has moved to the background.
*/
break;
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
/*
Release any memory that your app doesn’t need to run.
The device is running low on memory while the app is running.
The event raised indicates the severity of the memory-related event.
If the event is TRIM_MEMORY_RUNNING_CRITICAL, then the system will
begin killing background processes.
*/
break;
case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
/*
Release as much memory as the process can.
The app is on the LRU list and the system is running low on memory.
The event raised indicates where the app sits within the LRU list.
If the event is TRIM_MEMORY_COMPLETE, the process will be one of
the first to be terminated.
*/
break;
default:
/*
Release any non-critical data structures.
The app received an unrecognized memory level value
from the system. Treat this as a generic low-memory message.
*/
break;
}
}
}
onTrimMemory()
回调方法是在Android 4.0时候添加的,之前版本请用onLowMemory()
方法,跟TRIM_MEMORY_COMPLETE
事件处理一样。
四、分析App需要用多少内存
为了允许多个正在运行的进程,Android
为每个应用程序分配的堆大小设置了硬限制。确切的堆大小限制根据设备有多少总体可用RAM
不同而有所不同。如果您的应用程序已达到堆容量并尝试分配更多内存,则系统将引发OutOfMemoryError
。
为了避免OutOfMemoryError
内存不足,可以查询系统以确定当前设备上有多少可用的堆空间。你可以通过调用getMemoryInfo()
来查询这个数字。这将返回一个ActivityManager.MemoryInfo
对象,该对象提供有关设备当前内存状态的信息,包括可用内存,总内存以及内存阈值(即系统开始中断进程的内存级别)。 ActivityManager.MemoryInfo
对象还暴露了一个简单的布尔值,lowMemory
,可以判断你设备是否在低内存下运行。
如下例子,举例使用getMemoryInfo()
public void doSomethingMemoryIntensive() {
// Before doing something that requires a lot of memory,
// check to see whether the device is in a low memory state.
ActivityManager.MemoryInfo memoryInfo = getAvailableMemory();
if (!memoryInfo.lowMemory) {
// Do memory intensive work …
}
}
// Get a MemoryInfo object for the device’s current memory status.
private ActivityManager.MemoryInfo getAvailableMemory() {
ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return memoryInfo;
}
五、使用内存优化框架
一些Android
功能,Java类和代码构造倾向于使用比其他更多的内存。您可以通过在代码中选择更有效的替代方法来最大限度地减少应用程序使用的内存量
1. 谨慎使用Services
在不需要Services的情况下运行Services,是造成最严重的内存管理错误之一。
如果你的应用程序需要一个Services来在后台执行工作,那么除非它需要运行一个后台任务,否则不要让它保持运行。记得在完成任务时停止Services。否则,您可能会无意中造成内存泄漏。
当你启动一个Services时, 系统需要始终保持运行该Services的进程。此行为使得Services进程非常昂贵,因为Services使用的RAM对其他进程仍然不可用。这样可以减少系统在LRU
缓存中保留的缓存进程的数量,从而降低应用程序切换的效率。内存不足时系统甚至可能导致系统崩溃,系统无法维护足够的进程来承载当前运行的所有服务。
您通常应该避免使用持久性Persistent Services
,因为这些服务会常驻系统内存。相反,我们建议您使用诸如JobScheduler
之类的替代实现。有关如何使用JobScheduler
安排后台进程的更多信息,请参阅后台优化。
如果您必须使用服务,那么限制服务使用寿命的最好方法就是使用IntentService
,一旦完成了处理启动它的意图,IntentService
就会自动完成。有关更多信息,请阅读在后台服务中运行。
2.使用更优化的数据容器
编程语言提供的某些类未针对在移动设备上使用进行优化。例如,通用的HashMap
实现可能是相当低效的内存,因为每个映射都需要单独的入口对象。
Android
框架包括几个优化的数据容器,包括SparseArray,SparseBooleanArray和LongSparseArray
。例如,SparseArray
类更有效率,因为它们避免了系统需要自动复制密钥的情况,有时还需要创建另外一个或两个对象。
如有必要,您可以随时切换到原始数组以获得精简的数据结构。
3.使用nano protobufs进行序列化数据
协议缓冲区是一种语言中立,平台无关,可扩展的机制,由Google设计,用于序列化结构化数据 - 类似于XML
,但更小,更快,更简单。如果你决定为你的数据使用protobufs
,你应该总是在你的客户端代码中使用nano protobufs
。经常protobufs
生成非常详细的代码,这可能会导致您的应用程序中的许多种问题,如增加的RAM使用,APK
大小增加,和较慢的执行。
有关更多信息,请参阅protobuf自述文件中的“Nano版本”部分。
4.避免内存泄漏
如前所述,垃圾收集事件通常不会影响您的应用程序的性能。但是,很多短时间内发生的垃圾收集事件可能会很快消耗掉你的帧时间。系统花费在垃圾收集上的时间越多,执行其他内容(如渲染或流式传输音频)的时间就越少。
内存流失通常会导致大量的垃圾收集事件发生。在实践中,内存流失描述了在给定的时间内发生的分配的临时对象的数量。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
![](https://i-blog.csdnimg.cn/blog_migrate/03027879f785baa86434ebd107e54b0a.jpeg)
更多Android高级工程师进阶学习资料
进阶学习视频
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
id面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中…(img-g7tVAyhW-1713598474971)]
里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!