Android常用内存优化方式整理

  • 1、减小对象内存占用
    • 基本数据类型与包装类型
    • 枚举
    • Bitmap
    • 图片
    • 代码混淆
    • 序列化
  • 2、对象复用
    • 对象池
    • ListView/GridView/RecyclerView
    • Bitmap复用
  • 3、内存泄漏
    • 静态变量
    • 单例
    • 属性动画
    • 非静态内部类
    • 异步线程/任务
    • Handler
    • 资源未关闭
    • 全局集合对象
    • WebView
    • EditText
  • 4、内存使用策略优化
    • 优化布局,减少布局层次
    • StringBuffer/StringBuilder
    • 避免在onDraw(),创建对象
    • 选择合适的文件夹放置文件
    • 设计合适的缓存大小
    • 使用IntentService
    • 合理使用数据引用类型
    • SharePreference
    • 抽象
    • 反射

Android中,内存是十分宝贵的资源,内存优化有助于增加程序的流畅度提高用户体验,所以学习内存优化技是很有必要的。下面整理一些简单常用的性能优化方式。主要有以下几方面:

  1. 减小对象内存占用
  2. 对象复用
  3. 避免内存泄漏
  4. 内存使用策略优化

1、减小对象内存占用

基本数据类型与包装类型

与基本数据类型相比包装类型占用的内存更大,因此非必要情况不使用包装类型。例如:HashMap的Key或者 value为基础类型的情况下使用 SparseArray( SparseBooleanArray; SparseIntArray;SparseLongArray)替换, 或者在小数据量情况下使用 ArrayMap

拓展:ArrayMap与HashMap类似,都是使用键值对存储数据,考虑到内存优化的问题,Android优化了HashMap,也就是现在的ArrayMap。ArrayMap使用二分法对key从小到大排序,在删除,添加,查找元素的时候,使用二分查找法找到key所在的index,通过index找到对应的元素。所以ArrayMap适合于数据量偏小的场景,否则性能会变得很慢。ArrayMap使用两个数组存储,一个存储key的hash值,一个存储value。而HashMap使用的是数组+链表+红黑树

枚举

enum比起使用常量至少会增加2倍以上内存。
java中enum可以保证类型安全,提高代码的可阅读性;但是enum的每一个值都是对象,每个声明都会占用部分内存以便于引用到该对象,因此枚举会比Integer和String占用更多内存;替代方案,官方推出了@IntRef与@StringRef 两个注解来提供编译时的类型检查

Bitmap

Bitmap 极易消耗内存,减小Bitmap占用内存可以显著的减少内存占用。
优化措施:缩放,在图片载入内存之前,先行计算出一个合适的缩放比例,避免不必要的大图载入;解码格式选择:ARGN_8888/RG_565/ARGB_4444/ALPHA_8

图片

图片占用的内存远超文本,可以使用压缩后的图片,或者部分场景下使用shape绘制替代图片

代码混淆

减少不必要的类、类库;混淆可以去除无用代码,通过语意模糊对类,字段进行重命名,从而缩小,优化代码,差生更少量的映射

序列化

使用Parcelable进行数据传输;Parcelable是Android 特有的序列化类,性能比Serializable好,内存开销小,所以推荐在内存中传输数据时使用,但是由于是Android内特有类,所以在进行网速数据传输的时候不建议使用,建议使用Serializable,

不同版本的Parcelable的实现可能不同,所以也不推荐进行数据持久化时使用

2、对象复用

对象池

利用系统框架中某些既有复用特性,减少对象的重复创建,例如通过Message.obtain() 创建Message对象而不是new Message();Android系统本身也内置了很多的string,color,drawable,anim,style以及简单的layout等资源,这些都是能够在应用中直接引用的,这样不仅能减小APK大小,同时还能在一定程度上减小内存开销

ListView/GridView/RecyclerView

针对这种大量重复的子组件视图对ItemView进行复用

Bitmap复用

利用LRU cache机制对Bitmap 复用

3、内存泄漏

静态变量

静态变量的生存期为整个源程序
例如:将Activity的context对象赋值给全局静态变量,造成activity无法正常销毁

单例

单例的生存期根据初始化方式不同,开始时间不同,但是都从初始化开始一直到程序退出
例如:单例模式中实现观察者了模式,只在activity 中 注册了监听方法。没有在activity 中进行移除注册,就会引起内存泄漏

属性动画

无限循环播放的动画没有在onDestory中停止,动画就会一直播放,动画->View->Activity 这个引用链会造成Activity无法被正常销毁

非静态内部类

非静态内部类都隐式持有外部类的实例,造成外部类无法回收

异步线程/任务

异步线程/任务都是一个匿名内部类,都会持有当前外部类实例,会造成外部实例无法正常回收

Handler

Handler 会显式或者隐式持有当前Activity引用
在Activity 的onDestory()中关闭全部的当前的类的Hander;removeCallback(),removeMessage();removeCallbacksAndMessages

资源未关闭

对于使用BroadCastReceveiver,ContentObserver、File、Cursor、Stream、Bitmap等资源,应该在不使用的时候及时回收,否者这些资源不会被回收,造成内存泄漏;例如:在Activity销毁的时候回收

全局集合对象

集合类型对象如果只有添加方法,没有删除机制,会造成内存一直被占用,如果这个集合同时是全局性的变量,就会造成集合占用内存只增不减

WebView

WebView会造成的内存泄漏。
解决方案:
动态生成WebView,退出Activity 时候移除;
为加载WebView的Activity开启新的进程,并在该页面退出后关闭进程;
(推荐)从根源解决,WebView内存泄漏的主要原因是因为 WebView 注册了 component callbacks;但是反注册使用错误导致的;系统分别在attach和detach时进行了注册和反注册,但是 Activiy 比WebView 先执行了destory,这就会造成WebView不执行反注册,正确的写法是先在Activity 的onDestory()执行前先移除WebView,同时移除WebView绑定的服务,再执行Activity的super.onDestory()

EditText

EditText导致的内存泄漏 基本上都是因为键盘 inputMethManager 持有了EditTExt的引用,而EditTEext持有Activity引用造成的,但是由于Android系统碎片化并没有普适的方法解决,可以在Activity退出的时候,移除EditText断开引用链

常用的内存泄漏检查工具:
Android Profiler
LeakCanary

4、内存使用策略优化

优化布局,减少布局层次

越是扁平化的布局占用的资源就越少,同时也能优化View渲染的递归时间

StringBuffer/StringBuilder

在用到大量的字符拼接操作时候,可以考虑使用使用StringBuffer/StringBuilder而不是使用“+”拼接,减少内存抖动

避免在onDraw(),创建对象

在onDraw 等频繁调用的方法中,避免创建对象的操作,这会频繁GC造成内存抖动,(创建对象会增大内存开销,GC不是实时的)

选择合适的文件夹放置文件

hdpi/xhdp/xxhdpi等不同dpi的文件夹下的图片在不同的设备上会经过scale的处理。例如我们只在hdpi的目录下放置了一张100 * 100的图片,那么根据换算关系,xxhdpi的手机去引用那张图片就会被拉伸到200 * 200。需要注意到在这种情况下,内存占用是会显著提高的。对于不希望被拉伸的图片,需要放到assets或者nodpi的目录下

设计合适的缓存大小

在设计ListView/GridView/RecyclerView的Bitmap的 lru cache的时候要充分的考虑,应用程序剩余可用内存,屏幕上同时会渲染的图片数量,有多少的图片需要缓存,设备的 dpi是多少(hpdi的设备比mdpi的设备需要更大内存来缓存同样的数量)等等;

使用IntentService

当Service完成任务之后停止失败会引起内存泄漏,建议使用IntentService,它会在任务完成时候主动停止

合理使用数据引用类型

强引用:
强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。强引用其实也就是我们平时使用的Object strongReference = new Object();
软引用:
如果一个对象只具有软引用,则内存空间充足时,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。
软引用可以和一个引用队列(ReferenceQueue)联合使用。如果软引用所引用对象被垃圾回收,JAVA虚拟机就会把这个软引用加入到与之关联的引用队列中。

软引用可用来实现内存敏感的高速缓存

弱引用:
弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象
虚引用:
虚引用顾名思义,就是形同虚设。与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收

虚引用主要用来跟踪对象被垃圾回收器回收的活动。
虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。

SharePreference

SharePreference的操作会讲整个xml都读取到内存中,极易出现为读取其中的某一项而大量的无用数据读进内存

抽象

大多数情况下抽象类都是一种良好的编程习惯,因为抽象可以调好代码的灵活性与可维护性。但是没有个抽象类都会造成额外的内存开销,因此如果抽象类没有显著的提高效率,应该尽量避免使用

反射

Android 有相当一部分框架都通过反射来实现(如:Retrofit、ORMLite),这些框架往往可以简化代码。但是这个框架一般为了提升效率,往往会在内存中缓存大量的mapping,而且会长时间的保留在内存中。所以如何取舍就要看项目的实际需求了’

Android常用内存优化方式整理相关推荐

  1. 在Android开发中,有哪些好的内存优化方式?如何避免 Out Of Memory(OOM) ?

    在Android中,一个Process 只能使用16M内存,要是超过了这个限定就会跳出这个异常.  那么,开发中,有哪些措施能避免这个问题呢?不仅仅是Bitmap的处理,其他方面也会导致OOM.有哪些 ...

  2. Android 系统性能优化(41)---Android代码内存优化建议-OnTrimMemory优化

    Android代码内存优化建议-OnTrimMemory优化 OnTrimMemory 回调是 Android 4.0 之后提供的一个API,这个 API 是提供给开发者的,它的主要作用是提示开发者在 ...

  3. Rockchip Android平台内存优化及系统裁剪

    Rockchip Android平台内存优化及系统裁剪 文章目录 Rockchip Android平台内存优化及系统裁剪 编译32bit的Android系统 启用Android GO的配置 系统裁剪 ...

  4. Android的内存优化

    腾讯公司在五月三十一日开展[腾讯Bugly移动开发人员沙龙]大会.大会上面叶方正老师解说了 关于Android的内存优化的问题,只是我感觉叶老师许多其它的站在了測试的角度上去解释了这一方面,叶老师给我 ...

  5. Android 系统性能优化(42)---Android代码内存优化建议-Android资源篇

    Android代码内存优化建议-Android资源篇 这篇文章主要介绍在实际Android应用程序的开发中,容易导致内存泄露的一些情况.开发人员如果在进行代码编写之前就有内存泄露方面的基础知识,那么写 ...

  6. Android内存优化—Android的内存管理方式

    内存管理机制 从操作系统的角度来说,内存就是一块数据存储区域,属于可被操作系统调度的资源.现代多任务(进程)的操作系统中,内存管理尤为重要,操作系统需要为每一个进程合理的分配内存资源,所以可以从两方面 ...

  7. Android的内存优化的几种方案

    相信一步步走过来的Android从业者,每个人都会遇到OOM的情况.如何避免和防范OOM的出现,对于每一个程序员来说确实是一门必不可少的能力.今天我们就谈谈在Android平台下内存的管理之道,开始今 ...

  8. android开发内存优化的那些事儿

    一.Android应用程序内存优化   在开发Android App的过程中,经常会遇到内存方面的压力,比如OOM,或者频繁GC.本文不打算涵盖内存优化的所有方面,只是介绍一下我自己遇到的问题和解决方 ...

  9. Android Note - 内存优化

    内存优化是Android性能优化的重点内容,一般来说,谈及性能优化,肯定避不开内存优化.虽然现在手机内存都很大,但并不意味着我们的App在使用内存时能"为所欲为".这篇就简单地总结 ...

  10. Android中内存优化

    CSDN博客不写,排名会下降,我知道了...... Android内存优化,设计到很多方面,参考别大神的博客,自己也总结一下..... 下面将通过两篇博客,浅析Android 中的内存优化问题.来张图 ...

最新文章

  1. 52 介绍几个重要的类
  2. Zabbix-Proxy-agent实现web监控
  3. C语言编译链接生成可执行文件四大步骤:预处理(-E)->编译(-S)->汇编(-c) ->链接
  4. XenApp的工作过程
  5. xsmax进入dfu模式_iPhone XS/XS Max如何强制重启?如何进入恢复模式或DFU模式?
  6. php root 启动,php-fpm如何以root身份启动
  7. SEO优化工具之——Google Adwords 关键词工具
  8. 跨平台APP JQuery Mobile开发-张晨光-专题视频课程
  9. html5证书,1+X证书Web前端开发HTML专项练习
  10. golang import中的.和_的使用,import的几种方式点,下划线,别名
  11. 内固定取出术后护理_“钢铁侠“们注意了——身体内的钢板或内固定需要取出吗?...
  12. 电脑软件上的按钮原来是这样来的:按钮组件
  13. 计算机组成原理实验箱连接显示输出,计算机组成原理实验箱介绍.ppt
  14. Java中无法到达的语句
  15. adobe acrobat pro dc 无法打开PDF_pdf怎样转成word格式
  16. 计算机硬盘使用寿命,怎么看电脑硬盘的寿命
  17. 前端实战:利用CSS+HTML实现B站用户名片样式
  18. 百度学术打开不了?怎么办
  19. Android 插件开发实现
  20. win10无法更新计算机的启动配置,电脑升级win10后一开机关机总是显示正在配置更新请不要关闭您的计算机...

热门文章

  1. qlib里alpha158因子库的计算与缓存
  2. win7系统rpc服务器不可用无法开机,win7系统RPC服务器不可用的解决方法
  3. 常用web服务器架构理解
  4. mysql char archer_mysql - 常用sql
  5. android7.1修改默认休眠时间为1分钟
  6. Elasticsearch常用查询命令
  7. java中try-catch-finally的使用
  8. 软件推荐--Files2Folder
  9. Android 颜色透明度大全
  10. python3大小写转换函数_python字符串大小写转换