Android内存泄漏相关

来源:互联网 发布:诅咒淘宝店网址 编辑:程序博客网 时间:2024/06/11 05:18

我打算分两部分来进行说明。第一部分介绍下Android内存泄漏的几种可能,第二部分介绍遇到内存泄漏情况如何进行排查。

一直在说内存泄漏,包括实际项目中或者面试的时候,到底内存泄漏会引起什么呢?

首先就是程序运行越来越卡,程序响应慢甚至无响应。

第二就是当我的程序切到后台的时候回经常性被杀死,因为我们App占用内存过多,会极大可能地被干掉。最严重的就是直接OutOfMemory。

内存泄漏的几种场景

Bitmap的使用

1.图片Size

在使用Bitmap的时候,我们直接从美工那拿到切好的图直接使用,很容易造成内存泄漏。所以我们就必须对Bitmap进行处理,尽量从源头上减少内存的开销。特别是要展示一些缩略图或者对图片质量要求不怎么高的时候,就更应该进行设置。还记得大三暑假的时候参加的一个比赛,当时做的Android项目,在做引导界面的时候,直接使用美工提供的高清无码大图,结果直接滑到第三张的时候直接OOM,当时还很郁闷,找不到原因。

我们可以使用BItmapFactory.Options设置inSampleSize。该参数可以设置显示图的宽高分别为原始图片大小的几分之一。

相关代码如下:

BitmapFactory.Options bitmapFactoryOptions = new BitmapFactory.Options();

bitmapFactoryOptions.inJustDecodeBounds = true;

bitmapFactoryOptions.inSampleSize = 3;

options.inJustDecodeBounds = false;

Bitmap bmp = BitmapFactory.decodeFile(sourceBitmap,bitmapFactoryOptions);`

2.图片像素

除了图片的大小外,图片的像素也对内存的消耗有影响:

* ALPHA_8:每个像素占用1byte内存

* ARGB_4444:每个像素占用2byte内存

* ARGB_8888:每个像素占用4byte内存(默认)

* RGB_565:每个像素占用2byte内存

所以如果需求对图片的质量要求不是特别高就可以改下默认值,从而减少开销。

3.图片回收

在图片使用完之后,我们需要对图片进行回收,而不是等系统进行回收。

if(null != bitmap && !bitmap.isRecycled()){

bitmap.recyle();

bitmap = null;

System.gc();(只是建议进行垃圾回收,实际会不会回收无法预知)

}

以上步骤都做了,还是会出现异常的话,我们对使用Bitmap的地方进行OutOfMemory异常捕获,从而进行其他的处理,比如返回一张低分辨率的默认的图片。

对象引用方式不当

对象的引用方式分别有几下几种:

1. 强引用(StrongReference)

2. 软引用(SoftReference)

3. 弱引用(WeakReference)

4. 虚引用(PhantomReference)

下面来介绍下几种引用的区别。

强引用:Object obj = new Object();这个就是强引用,JVM哪怕发生OOM错误也不会回收该对象。

软引用:当内存不够使用时才回收。

弱引用:不管内存是否够用都会回收。

虚引用:和没有任何引用一样,随时都可能被回收。

浮点数的使用过多

使用浮点数会降低效率,增大开销。所以应避免大量浮点数的使用。

ListView使用不当

使用ListView的时候一定要注意是否存在内存泄漏,特别是对于Item条目过多的时候。

具体可以参考我上一篇博客:https://rainyandsunny.github.io/2016/11/03/ListView%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/

Cursor回收

一般情况下我们都会对cursor进行回收,使用完直接关闭,这是个好习惯。

不管我们是做后台或者是做Android开发,这一点大家都很熟悉。但是在使用CursorAdapter的时候就不能关闭啊,关闭了拿不到数据。这就要求我们在ListView所在的Activity的onDestory()中对cursor进行关闭。

类似的还有:广播一定要unregisterReceiver。I/O流等都要记得使用完及时关闭。

Context

尽量使用ApplicationContext而不是Activity,因为引用的实例的生命周期很有可能超出Activity的生命周期,从而造成Activity无法回收,导致内存泄漏。

UI方面

1. 在XML中写布局的时候,都很爽,闭着眼睛都能写,一点码农的感觉,记着我们是工程师,改变世界的那种。但是对写出来的UI一定要记得进行检查,看布局是否合理,是否存在多余节点。幸好Google给我们开发者提供了一款工具用来检查UI视图层级:hierarchyviewer,在SDK tools目录下,至于工具的使用就不介绍了,总之大家一定要有这个意识,写一部分就检查一部分,不要到最后越积越多,哭都来不及。一定要记得!!!!

2. ViewStub标签的使用

我记得Android高级编程中是这么介绍的,懒加载。就是在使用的时候再进行设置,显式地调用inflater或者置为可见的时候才会被填充。

3. merge标签

当含有merge标签的布局被添加到另一个布局文件的时候,该merge标签会被删除,直接将子view进行添加。

4. include标签

一个app里面肯定会有相同的布局,特别是在多人合作的时候,不要你写一个,我写一个。写一份,然后include到需要的父布局中即可。

其他小的Tips

1. View中设置缓存属性.setDrawingCache为true。

2. Android提供给我们的两个工具procstats,meminfo。他们一个侧重于后台的内存使用,另一个是运行时的内存使用。

使用方法:adb shell dumpsys procstats --hours 3(数字自己指定)

adb shell dumpsys meminfo

3. 循环中条件中尽量不要进行相关计算,比如:

for(int i=0;i<arr.lenth;i++){}

类似于这种的,用个变量保存没多大坏处。

4. 我感觉自己有强迫症,老是调用别人的东西就感觉不爽,就喜欢自己实现。但是有些东西,java本身给我们提供了的,就不要自己用java语言再去实现了,因为这样会降低效率,java自己的实现本身有优化。这一点上特别是java对String的处理上。Formatter,DateFormat,TextUtils,MemoryFile等等。这不是拿来主义,我们的目的是提高效率,降低内存的使用。如果有兴趣可以看看别人的实现。

下篇简单讲讲怎么样查找内存泄漏。
0 0
原创粉丝点击