android APP性能优化之内存优化

APP内存优化方法

1.数据结构优化

2.对象复用

3.避免内存泄漏

数据结构优化

1.频繁地使用字符串拼接不要用“+”的方式,应该使用StringBuilder,“+”的方式会产生无用的中间变量,而且难以删除

2.ArrayMap和SparseArray替换HashMap

HashMap效率较低,内存占用较高,使用前两者能解决这种问题。HashMap中的一个entry需要额外占用32B

3.内存抖动

length=200000;

android APP性能优化之内存优化_第1张图片

由于length比较大,每次new String[length]时,都会占用比较大的新生代空间,很有可能此时新生代空间满了,所以,会进行Minor GC(其他线程在此时处于停止状态),并且这回出现多次。APP运行效率降低。

如何解决?

直接将上面这行语句放在循环外面就行。

android APP性能优化之内存优化_第2张图片

在android Monitor中可以看到这样的内存锯型图

对象复用

1.复用系统自带的资源

比如使用Application Context而不用 Activity Context(后面有讲到)

2.ListView/GridView的ConvertView复用

3.避免在onDraw方法里面执行对象的创建

内存泄漏

内存泄漏:由于代码瑕疵,导致这块内存,虽然是停止不用了,但依然被其它东西占用着,使GC没办法对它回收。


android APP性能优化之内存优化_第3张图片

打开这个线程的Activity,然后退出,再打开,在退出,重复操作,你会发现这个activity占用内存越来越大。

android APP性能优化之内存优化_第4张图片

android APP性能优化之内存优化_第5张图片

android APP性能优化之内存优化_第6张图片

不断的重复,并且点击GC后,你会发现110这个数据一直在变大。

为甚么?我们在关闭这个activity时,由于这个线程睡眠了5分钟,所以它在关闭后还会存在,系统没办法对它进行回收。当再次打开这个activity时,上面一个activity就会成为内存泄漏的罪魁祸首。

从上面可以看出,Activity是很容易发生泄漏的

所以对于程序来说,用Application Context而不用Activity Context。

还有一点。要注意Cursor对象是否及时关闭,没有关闭的话,也容易出现内存泄漏。

OOM问题

问题分析:

1.内存泄漏

2.OOM绝大部分发生在图片

四种基本引用

(1) 强引用(StrongReference)

强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

(2)弱引用(WeakReference)

弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象

弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

(3)软引用(SoftReference)

如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

(4)虚引用(PhantomReference)

“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。

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

应用场景

WeakReference与SoftReference都可以用来保存对象的实例引用,这两个类与垃圾回收有关。

WeakReference是弱引用,其中保存的对象实例可以被GC回收掉。这个类通常用于在某处保存对象引用,而又不干扰该对象被GC回收,通常用于Debug、内存监视工具等程序中。因为这类程序一般要求即要观察到对象,又不能影响该对象正常的GC过程。

强引用、软引用详解


android APP性能优化之内存优化_第7张图片

变量在Activity中方法外声明时,像strongref,它是跟随activity的销毁而销毁。并且strongref是强引用,就算这个变量没有再使用,也不会因为内存不足而回收(也就是说,栈中内存在运行期间不会被回收?);同理,如果一个变量是在方法中声明,那么它是跟随方法的结束而销毁。

针对这种变量没有用了,却依旧占用内存的情况,我们可以使用软引用来解决这种问题。

图片加载时,也可以使用软引用来解决图片加载进内存,大量占用内存的问题,方式:可以将图片存储在一个引用数组中,当内存不够用时,可以释放其中的部分图片,当需要再次使用时,再重新加载。


android中有一个方法:void onTrimMemory(int level)用来得到当前activity的内存信息,当内存不够时,方便程序猿做出相应的处理。如果是后台信息,可以选择清理掉内存,如果是前台,几乎不会被清理。

  • TRIM_MEMORY_COMPLETE:内存不足,并且该进程在后台进程列表最后一个,马上就要被清理 ConstantValue 80

  • TRIM_MEMORY_MODERATE:内存不足,并且该进程在后台进程列表的中部。   ...60

  • TRIM_MEMORY_BACKGROUND:内存不足,并且该进程是后台进程。       ...40

  • TRIM_MEMORY_UI_HIDDEN:内存不足,并且该进程的UI已经不可见了。      ...20

      以上4个是4.0增加

  • TRIM_MEMORY_RUNNING_CRITICAL:内存不足(后台进程不足3个),并且该进程优先级比较高,需要清理内存 ...15

  • TRIM_MEMORY_RUNNING_LOW:内存不足(后台进程不足5个),并且该进程优先级比较高,需要清理内存...10

  • TRIM_MEMORY_RUNNING_MODERATE:内存不足(后台进程超过5个),并且该进程优先级比较高,需要清理内存 ...5     



优化OOM问题的方法

1.注意临时bitmap对象的及时回收

2.避免Bitmap的浪费

3.Try catch 某些大内存分配的操作(可以使程序不会崩溃,但也不会正常运行,毕竟内存不够了)

4.加载Bitmap:缩放比例、解码格式、局部加载

5.通过软引用的方式加载图片

关于4、5的源码网上有许多可以自己去搜索。

视频教学网址:https://www.imooc.com/video/13673

你可能感兴趣的:(android)