内存优化的套路:
一. 使用更加优化的数据结构
一般来说,使用优化的数据结构,并不会给程序带来太多的内存上的节约。但是要综合来看,结合程序的逻辑。比如循环中使用某种数据结构等。养成良好的编码习惯是开发出高效app的重要一环。
1)使用sparseArray 替代hashmap
2)stringbuffer stringbuild 代替String 。尤其在有累加操作的时候
tips: 除非有循环,否则效果,微乎其微,但贵在养成良好的编码习惯
3)使用静态常亮代替枚举
tips: 枚举开发者友好,简单的枚举已经被编译器处理为静态常量,并不影响内存。
4)使用合适大小的容器,能用更小的用更小的
tips:比如作者之前曾经接手过一个比特币交易的项目,里面牵涉到很多小数点位,合理的产品沟通。能用更小的容器用更小的容器。后面牵涉到运算,实际上还要要谨慎的。养成良好习惯。
1.StringBuffer和StringBuilder初始化默认大小为16个字符
2.HashMap初始化默认大小16,自增为2n.
3.HashTable默认初始值为11,加载因子为0.75,自增为2n+1
4.ArrayList初始化默认值为10,自增为1.5n
5.Vector初始化默认值为10,自增为2n
byte:8位,最大存储数据量是255,存放的数据范围是-128~127之间。
short:16位,最大数据存储量是65536,数据范围是-32768~32767之间。
int:32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1。
long:64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1。
float:32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。
double:64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。
boolean:只有true和false两个取值。
char:16位,存储Unicode码,用单引号赋值。
tips: 无需强制去记忆,因为它们的值都已经以常量的形式定义在对应的包装类中了。如:基本类型byte 最大值:Byte.MAX_VALUE基本类型short 最大值 Short.MAX_VALUE
二. 解决所有的内存泄漏
1)辅助系列:
使用dump来查看是否泄漏
Android内存泄漏快速解决——三大工具
android内存泄漏快速解决——模板泄漏代码
2)解决系列:
android内存泄漏快速解决——正确处理handler
android内存泄漏快速解决——一个方法解决70%的泄漏
怎么解决这个问题,思路就是避免使用非静态内部类,定义内部类时,要么是放在单独的类文件中,要么就是使用静态内部类。因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露。当你需要在静态内部类中调用外部的Activity时,我们可以使用弱引用来处理。
3)案例:leakCanary观测到的泄漏:
android内存泄漏快速解决——构造方法里不能出现非弱引用的对象的实例化
4)其他正在处理中的泄漏:
android内存泄漏快速解决——fragment的rootview泄漏
android内存泄漏快速解决——系统源码泄漏
viewpager+fragment滑动泄漏
使用三方库加载图片一般不会出内存问题,但是需要注意图片使用完毕的释放,而不是被动等待释放。
三. 谨慎使用图片
1)找到合适时机,清除图片缓存
使用三方库加载图片一般不会出内存问题,但是需要注意图片使用完毕的释放,而不是被动等待释放。
在合理的时机调用glide清理内存:
app结束后,快速降低图片内存的一个方法
经Performance monitor追踪,确实可以在app结束后,快速降低内存(图片占用部分)。
参考网上资料,添加内存处理:
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
if (level== ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN){
Glide.get(this).clearMemory()
}
Glide.get(this).trimMemory(level)
}
override fun onLowMemory() {
super.onLowMemory()
Glide.get(this).clearMemory()
}
2) 敲定是图片造成的内存增大
android 8.0 和3.0-7.0的bitmap的内存存储空间由堆内存进化为了native内存:
native.png 一款百万级的app“内存溢出”问题的友盟跟踪结果
可以看到友盟捕获的内存溢出发生在8.0系统一下,泾渭分明。此时,则要开始怀疑是图片造成的oom,无他,图片是oom的大户。此时很值得怀疑了。
3) 使用webp
image.png四.避免内存抖动**
- 避免在循环中创建临时对象;
- 避免在onDraw中创建Paint、Bitmap对象等。
五. 使用onTrimMemory根据不同的内存状态做相应处理**
六. Library的使用**
- 去掉无用的Library,对生成的Apk进行反编译查看使用到的Library,避免出现无用的Lib仍然被打进Apk;
- 避免引入巨大的Library;
- 使用Proguard进行混淆、压缩。
关于性能优化,一些的问题最终变成内存问题——《Android 移动性能实战》
这里以oom为起点介绍Android内存的原理。
在升高的内存曲线中:不明白参考:Android内存泄漏快速解决——三大工具章节的Memory Monitor的使用
去找到实现方式可能存在的问题:例如启动页闪屏图,show完毕之后应该释放掉Bitmap。
一些实现方式看起来没有问题实现了功能但是实际上可能对内存造成了影响。我在使用Heap Viewer查看Bitmap对象时发现了一张只需下载不应该被加载的图。
image.png
参考文献:
《Android 高性能变编程》【西班牙】Enrique López Mañas(恩里克·洛佩斯·马尼亚斯),【意】Diego Grancini (迪戈·格兰奇尼)著叶坤 译
《Kotlin实战》【俄】Dmitry Jemerov Svetlana Isakova 著 覃宇 罗丽 李思阳 蒋扬海 译
《重构改善既有代码设计》【美】马丁福勒(MartinFowler)著 熊节 林从羽译
Android app性能调优
网友评论