随着硬件设置的不断发展,手机内存从原来的kb单位,发展到现在的G为单位,但是手机内存总还是有限的,所以我们就要在开发当中尽量的做到内存的优化。
1,首先应该知道哪些原因可能bitmap内存消耗过大,导致OOM
这个问题是android开发一直伴随我们的问题,解决问题也是老生常谈,可以通过以下步骤来减少内存消耗:
(1),图片的大小(面积)的压缩,下面是一段熟悉的代码
- BitmapFactory.Options bitmapFactoryOptions =new BitmapFactory.Options();
- bitmapFactoryOptions.inJustDecodeBounds =true;//设置成true只能度,这样只能读出图片的大小不能得到图片
- bitmapFactoryOptions.inSampleSize =2;//缩小为原来的二分之一
- // 这里一定要将其设置回false,因为之前我们将其设置成了true
- // 设置inJustDecodeBounds为true后,decodeFile并不分配空间,即,BitmapFactory解码出来的Bitmap为Null,但可计算出原始图片的长度和宽度
- options.inJustDecodeBounds =false;
- Bitmap bmp = BitmapFactory.decodeFile(sourceBitmap, options);
(2),图片像素
Android图片中有四中属性,分别是:
ALPHA_8:每个像素占用1byte内存
ARGB_4444:每个像素占用2byte内存
ARGB_8888:每个像素占用4byte内存(默认的)
RGB_565:每个像素占用内存2byte内存
占用内存越大显示图片质量越好,但是鱼和熊掌不能兼得,如果对图片质量要求没那么高我们可以选择低内存的设置,
如经常用到的RGB_565(没有透明度属性),示例代码如下:
- publicstaticBitmapreadBitMap(Contextcontext, intresId) {
- BitmapFactory.Optionsopt = newBitmapFactory.Options();
- opt.inPreferredConfig = Bitmap.Config.RGB_565;
-
/* 如果 inPurgeable 设为True的话表示使用BitmapFactory创建的Bitmap * 用于存储Pixel的内存空间在系统内存不足时可以被回收, * 在应用需要再次访问Bitmap的Pixel时(如绘制Bitmap或是调用getPixel), * 系统会再次调用BitmapFactory decoder重新生成Bitmap的Pixel数组。 * 为了能够重新解码图像,bitmap要能够访问存储Bitmap的原始数据。 * * 在inPurgeable为false时表示创建的Bitmap的Pixel内存空间不能被回收, * 这样BitmapFactory在不停decodeByteArray创建新的Bitmap对象, * 不同设备的内存不同,因此能够同时创建的Bitmap个数可能有所不同, * 200个bitmap足以使大部分的设备重新OutOfMemory错误。 * 当isPurgable设为true时,系统中内存不足时, * 可以回收部分Bitmap占据的内存空间,这时一般不会出现OutOfMemory 错误。 - */
- opt.inPurgeable =true;//简单一句话内存不足的时候,可以清楚
- opt.inInputShareable =true;//;// 以上options的两个属性必须联合使用才会有效果
- //获取资源图片
- InputStreamis = context.getResources().openRawResource(resId);
- returnBitmapFactory.decodeStream(is,null, opt);
- }
(3),图片的回收:
在使用完bitmap之后,要及时的进行手动回收,从而保障内存少的浪费
- // 先判断是否已经回收
- if(bitmap != null && !bitmap.isRecycled()){
- // 回收并且置为null
- bitmap.recycle();
- bitmap =null;
- }
- System.gc();
(4),在有可能出现问题的地方尽量try......catch,避免程序的崩溃
(5),下载图片的流程
为了加快图片的加载速度,流行的加载方法是三级缓存方法①现存内存中取数据②内存取不到,异步从本地取,然后在存入缓存③本地取不到,异步从网络取图,然后存入本地存入缓存。最常用的图片存取的算法是LRU,重要类是lrucache。
2,对于数据库中的cursor,流操作时要注意末尾要close掉。
3,尽量避免static成员变量引用资源耗费过多的实例
比如Context因为Context的引用超过它本身的生命周期,会导致Context泄漏。所以尽量使用Application这种Context类型。 你
可以通过调用Context.getApplicationContext()或 Activity.getApplication()轻松得到Application对象。
4,尽量少创建不必要的对象和重复创建对象,如果一个对象说在多出使用尽量使用单例模式进项创建,String中不要使用太多的+"",没加一次都会创建新的对象,对象的创建泛滥会导致堆内存的大量浪费。
5,大家都知道android界面是解析xml树形结构而得到的,这时候如果树形结构太“深”就会增加内存的消耗,简洁的布局结构也是内存优化的关键。
6,long占8个,float占8个,double占16个如果没必要尽量避免使用这些占用内存比较大的数据类型
7,如果内存要求比较严格的时候尽量避免使用枚举类型。
8,for循环的时候要尽量避免使用双层嵌套,同时不要在for中调用任何其他方法
9,adapter适配器使用的时候经典的convertview和viewholder的使用,避免了每次创建新的界面。
10,pooL池的思想,如线程池,String,等这些避免了对象的过度创建。
11,多看一下java的开发模式,让代码要尽量符合面相对象的思想,做到易维护,易扩展,易复用,灵活多变
12,在做网络请求的时候避免过度访问,最好做一下本地缓存。
参考:http://blog.csdn.net/hewence1/article/details/39004301