如何控制应用程序使用的内存?

1. 记得关闭启动的服务

当服务中的任务完成后,要记得停止该服务。可以考虑使用 IntentService,因为 IntentService 在完成任务后会自动停止。

2. UI 不可见时释放资源

  • onStop 中关闭网络连接、注销广播接收器、释放传感器等资源;
  • onTrimMemory() 回调方法中监听 TRIM_MEMORY_UI_HIDDEN 级别的信号,此时可在 Activity 中释放 UI 使用的资源,大符减少应用占用的内存,从而避免被系统清除出内存。

3. 内存紧张时释放资源

运行中的程序,如果内存紧张,会在 onTrimMemory(int level) 回调方法中接收到以下级别的信号:

  • TRIM_MEMORY_RUNNING_MODERATE:系统可用内存较低,正在杀掉 LRU 缓存中的进程。你的进程正在运行,没有被杀掉的危险。
  • TRIM_MEMORY_RUNNING_LOW:系统可用内存更加紧张,程序虽然暂没有被杀死的危险,但是应该尽量释放一些资源,以提升系统的性能(这也会直接影响你程序的性能)。
  • TRIM_MEMORY_RUNNING_CRITICAL:系统内存极度紧张,而 LRU 缓存中的大部分进程已被杀死,如果仍然无法获得足够的资源的话,接下来会清理掉 LRU 中的所有进程,并且开始杀死一些系统通常会保留的进程,比如后台运行的服务等。(关于进程的优先级,参考这里

当程序未在运行,保留在 LRU 缓存中时, onTrimMemory(int level) 中会返回以下级别的信号:

  • TRIM_MEMORY_BACKGROUND:系统可用内存低,而你的程序处在 LRU 的顶端,因此暂时不会被杀死,但是此时应释放一些程序再次打开时比较容易恢复的 UI 资源。
  • TRIM_MEMORY_MODERATE:系统可用内存低,程序处于 LRU 的中部位置,如果内存状态得不到缓解,程序会有被杀死的可能。
  • TRIM_MEMORY_COMPLETE:系统可用内存低,你的程序处于 LRU 尾部,如果系统仍然无法回收足够的内存资源,你的程序将首先被杀死。此时应释放无助于恢复程序状态的所有资源。

注:该 API 在版本 14 中加入。旧版本的 onLowMemory() 方法,大致相当于 onTrimMemory(int level) 中接收到 TRIM_MEMORY_COMPLETE 级别的信号。

另:尽管系统主要按照 LRU 中顺序来杀进程,不过系统也会考虑程序占用的内存多少,那些占用内存高的进程有更高的可能性会被首先杀死。

 

4. 确定你的程序应该占用多少内存

可以通过 getMemoryClass()来获取你的程序被分配的可用内存,以 M 为单位。

你可以通过在 <application> 标签下将 largeHeap 属性设为 true 来要求更多的内存,这时通过 getLargeMemoryClass() 方法来获取可用内存。

大部分应用程序不需要使用此功能,因此使用该标签前,确认你的程序是否真的需要更多内存。使用更多内存会对整个系统的性能产生影响,而且当程序进入 LRU 时会更容易首先被系统清理掉。

5. 正确使用 Bipmap,避免浪费内存

如果你的 ImageViwe 的尺寸只有 100 * 100,那么没有必要将一张 2560 * 1600 的图片整个加载入内存。关于如何加载图片,参考这里

6. 使用 Android 提供的优化过的数据结构

如 SparseArray, SparseBooleanArray, LongSparseArray 等,相比 Java 提供的 HashMap,这些结构更节省内存。

 

7. 始终对内存使用情况保持关注

  • 枚举类型 Enum 会比静态常量占用更多的内存;
  • Java 中每个类(包括匿名内部类)都占用至少 500 字节左右的代码;
  • 每个类的实例会在 RAM 中占用大约 12 ~ 16 字节的内存;
  • 每向 HashMap 中添加一个 Entry 时,新生成的 Entry 占用大约 32 个字节。

8. 谨慎使用第三方类库

这些外部类库可能原先并非针对移动平台,因此未进行过优化,在使用前应注意。另外尽量不要因为一两个特性而使用一个体积很大的类库。

 

9. 使用 ProGuard

使用 ProGuard 移除无用的代码并重命名一些类、字段、方法等,使你的代码更紧凑,节省内存空间。

10. 使用 zipalign

zipaligned 对最终打包的 apk 进行字节对齐。

注:Google Play 不接受未对齐过的 apk。

11. 分析内存使用情况

如果已经获得一个相对稳定的版本,应对程序整个生命周期的内存使用状况进行分析。参考这里

12. 使用多个进程

如果程序需要执行大量的后台工作,可考虑将程序分为两个进程,一个进程负责 UI,另一个进程负责后台任务。比如音乐播放器。

代码示例:

<serviceandroid:name=".PlaybackService" android:process=":background"/>

android:process属性的值以“:”开头,名称可任意选取。

在决定是否使用多进程前,应注意,一个不执行任何任务的空进程至少也要占用 1.4 MB 内存。

另外要注意进程的相互依赖性,比如如果将 ContentProvider 放在 UI 进程中,而后台任务进程也需要调用 ContentProvider,就会导致 UI 进程一直保留在 RAM 中。

控制 Android 程序使用的内存的更多相关文章

  1. windows下使用adb工具查看android程序cpu和内存消耗情况

    在实际的开发当中,尤其软件运行在一个硬件设备比较差的环境下,对软件占用资源大的问题是开发者们必须要解决的问题,系统比较卡.觉得应该看看程序的cpu和内存消耗 一直以来都在windows下编程,已经习惯 ...

  2. 在Eclipse中使用MAT分析Android程序内存使用状况(转)

    对于Android这种手持设备来说,通常不会带有太大的内存,而且一般用户都是长时间不重启手机,所以编写程序的时候必须要非常小心的使用内存,尽量避免有内存泄露的问题出现.通常分析程序中潜在内存泄露的问题 ...

  3. Android内存管理(5)*官方教程:Logcat内存日志各字段含义,查看当前内存快照,跟踪记录内存分配,用adb查看内存情况时各行列的含义,捕获内存快照的3种方法,如何让程序暴漏内存泄漏的方法

    Investigating Your RAM Usage In this document Interpreting Log Messages                 内存分析日志中各消息的含 ...

  4. Android 如何有效的解决内存泄漏的问题

    前言:最近在研究Handler的知识,其中涉及到一个问题,如何避免Handler带来的内存溢出问题.在网上找了很多资料,有很多都是互相抄的,没有实际的作用. 本文的内存泄漏检测工具是:LeakCana ...

  5. 给Android程序员的六个建议

    给Android程序员的六个建议 分类: 安卓相关2015-07-14 23:58 177人阅读 评论(0) 收藏 举报 android程序员 如果你一年前写的代码 , 在现在看来你还感觉写的很不错 ...

  6. android 开发如何做内存优化

    不少人认为JAVA程序,因为有垃圾回收机制,应该没有内存泄露.其实如果我 们一个程序中,已经不再使用某个对象,但是因为仍然有引用指向它,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造 ...

  7. Android程序开发0基础教程(一)

    程序猿学英语就上视觉英语网 Android程序开发0基础教程(一)   平台简单介绍   令人激动的Google手机操作系统平台-Android在2007年11月13日正式公布了,这是一个开放源码的操 ...

  8. 谈使用Eclipse与DDMS调试Android程序的方法

    在Eclipse开发工具中调试程序的方法很多,但是使用Eclipse调试Android程序时需要注意一些细节上的问题.许多刚接触 Android的开发者,在调试Android程序时总是不能迅速地找到程 ...

  9. Android 程序框架设计

    这篇文章主要内容来自于之前我讲的一个PPT文档,现在将其整理如下.欢迎指正.以下的内容都是来自于我自身的经验,欢迎大家多提自己的建议. 1.一些概念 模式的定义: 每个模式都描述了一个在我们的环境中不 ...

随机推荐

  1. 开刷LeetCode

    还是觉得自己在算法这块太弱鸡了 不多废话开刷吧,LeetCode与算法导论相辅相成双管齐下,期望能填上算法这个坑 解法没意外都是用Python2.7 由于LeetCode有提供Top Solution ...

  2. Eclipce结合Ant进行编译、打包、传输、运行

    注意: 用Ant构建时,build path只能是单级的,如默认的src,如果是类似basePath/jsr253这样的话,运行Ant build时会报错,说找不到jsr253. (此文讲述的是以an ...

  3. 如何用qq代理发送邮件

    今天我想写一篇服务器发送验证邮件的的文章,我查阅过其他博客里面写的文章,都是可以实现的,但是对于初学者来说是一个很痛苦的事情,很多代码看不懂,原因有多种,写的多,写的乱,然后就不想往下看了.我今天详细 ...

  4. javascript中的预编译问题

    Js作为脚本语言,可以不需要编译直接运行,但遇到类似变量或者函数同名,预编译方面的知识可以帮助我们更好解决问题. 示例: 这是一段js中普通的函数调用代码 <script>1.    // ...

  5. 数据复制与AA双活(1)

    最开始有些概念需要弄明白: 1. 什么是RPO? Wiki: https://en.wikipedia.org/wiki/Recovery_point_objective A recovery poi ...

  6. sublime如何自动保存

    sublime是前端开发者喜欢使用的工具,它有很多快捷方式可以让我们快速的编写代码:在开发过程中,每次修改代码之后都要按Ctrl+S保存.在这里向大家介绍一下如何设置让它自动保存. 一.打开subli ...

  7. 使用 jsoup 对 HTML 文档进行解析和操作

    jsoup 简介 Java 程序在解析 HTML 文档时,相信大家都接触过 htmlparser 这个开源项目,我曾经在 IBM DW 上发表过两篇关于 htmlparser 的文章,分别是:从 HT ...

  8. DataGridView回车焦点横向移动

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)        {            if (keyData ...

  9. 私有无线传感网 PWSN HLINK

    私有无线传感网,我把其叫做 Personal Wireless Sensor Network.此种网络最另众人所知的就是ZIGBEE了.由于在用户不同的使用场景中,对传感网络有许多不同的要求,例如:通 ...

  10. OpenCv ROI操作

    Mat img, dst; Rect imgroi(, , img.cols, img.rows);//小图像img需要复制到大图的像素区域rect Rect dstroi(, , img.cols, ...