我是靠谱客的博主 儒雅金针菇,最近开发中收集的这篇文章主要介绍Android加载大图片OOM异常解决,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

项目用到加载大图片,app老是出现OOM异常,总结了几点经验,供参考。

1、手动干涉dalvik的堆内存处理效率:

1
private final static float TARGET_HEAP_UTILIZATION = 0.75f;
2
//for same activity
3
public void onCreate()
4 
{
5 
…………
6 
VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);
7 
…………
8
}

2、手动指定Android堆大小:

1
private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
2
//for same activity
3
public void onCreate()
4 
{
5 
…………
6
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。当然对于内存吃紧来说还可以通过手动干涉GC去处理

7 
…………
8
}

3、手动指定回收内存,指定gc:

1
if(bitmap!=null && !bitmap.isRecycled())
2 
{
3 
bitmap.recycle();
4 
System.gc();
5
}

4、图片必须进行缩放,不然多半会出OOM:

 1
/**
 2 
* @param url
 3 
*
图片的url
 4 
* @param sc
 5 
*
,显示的像素大小
 6 
* @return 返回指定RUL的缩略图
 7 
*
 8 
* @author jevan 2012-7-3
 9 
*
10
*/
11
public static Bitmap loadImageFromUrl(String url, int sc)
12 
{
13
14 
URL m;
15
InputStream i = null;
16
BufferedInputStream bis = null;
17
ByteArrayOutputStream out = null;
18
19
if (url == null)
20
return null;
21
try
22 
{
23
m = new URL(url);
24
i = (InputStream) m.getContent();
25
bis = new BufferedInputStream(i, 1024 * 4);
26
out = new ByteArrayOutputStream();
27
int len = 0;
28
29
while ((len = bis.read(isBuffer)) != -1)
30 
{
31
out.write(isBuffer, 0, len);
32 
}
33 
out.close();
34 
bis.close();
35
} catch (MalformedURLException e1)
36 
{
37 
e1.printStackTrace();
38
return null;
39
} catch (IOException e)
40 
{
41 
e.printStackTrace();
42 
}
43
if (out == null)
44
return null;
45
byte[] data = out.toByteArray();
46
BitmapFactory.Options options = new BitmapFactory.Options();
47
options.inJustDecodeBounds = true;
48
BitmapFactory.decodeByteArray(data, 0, data.length, options);
49
options.inJustDecodeBounds = false;
50
int be = (int) (options.outHeight / (float) sc);
51
if (be <= 0)
52 
{
53
be = 1;
54
} else if (be > 3)
55 
{
56
be = 3;
57 
}
58
options.inSampleSize = be;
59
Bitmap bmp =null;
60
try
61 
{
62
bmp = BitmapFactory.decodeByteArray(data, 0, data.length, options); //返回缩略图
63
} catch (OutOfMemoryError e)
64 
{
65
// TODO: handle exception
66
MainActivity.print("Tile Loader (241) Out Of Memory Error " + e.getLocalizedMessage());
67
68 
System.gc();
69
bmp =null;
70 
}
71
return bmp;
72
}

把上面几条全部用上,OOM的异常基本上能完全避免!!!

 

以下内容为转载,收藏。

 1
//我们在BitmapManager.instance().decodeFile对图片进行解码,生成Bitmap的时候,我们会发现很多大图片会报OutOfMemoryError的错误,这个时候我们需要改变options里面的一些参数来解决这个问题,不然我们程序就跑不下去了。最简单的方法就是改变options.inSampleSize这个参数,把它增大,就可以解决很多图片OutOfMemoryError的问题。
 2
//下面是一个使用了这个方式的代码
 3
public static Bitmap makeBitmap(String path, int minSideLength, int maxNumOfPixels, BitmapFactory.Options options)
 4 
{
 5
Bitmap b = null;
 6
Log.i(TAG, "makeBitmap : path = " + path);
 7
if (path == null)
 8
return null;
 9
File f = new File(path);
10
11
//try {
12
// b = BitmapManager.instance().decodeFile(f, null);
13
//} catch (OutOfMemoryError ex) {
14
// Log.e(TAG, "Got oom exception, we may try one more time, using Options:" + ex.getMessage());
15
if (options == null)
16 
{
17
options = new BitmapFactory.Options();
18 
}
19
20
try
21 
{
22
options.inJustDecodeBounds = true;
23 
BitmapManager.instance().decodeFile(f, options);
24
if (options.mCancel || options.outWidth == -1 || options.outHeight == -1)
25 
{
26
return null;
27 
}
28
options.inSampleSize = computeSampleSize(options, minSideLength, maxNumOfPixels);
29
options.inJustDecodeBounds = false;
30
options.inDither = true;
31
options.inPreferredConfig = null;//Bitmap.Config.ARGB_8888;
32
33
b = BitmapManager.instance().decodeFile(f, options);
34
} catch (OutOfMemoryError ex2)
35 
{
36
Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize + " minSideLength = "
37
+ minSideLength + " maxNumOfPixels =" + maxNumOfPixels, ex2);
38
try
39 
{
40
options.inSampleSize += 1;
41
options.inJustDecodeBounds = false;
42
options.inDither = true;
43
options.inPreferredConfig = null;
44
b = BitmapManager.instance().decodeFile(f, options);
45
} catch (OutOfMemoryError e)
46 
{
47
Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize + " minSideLength = "
48
+ minSideLength + " maxNumOfPixels =" + maxNumOfPixels, e);
49
try
50 
{
51
options.inSampleSize += 1;
52
options.inJustDecodeBounds = false;
53
options.inDither = true;
54
options.inPreferredConfig = null;
55
b = BitmapManager.instance().decodeFile(f, options);
56
} catch (OutOfMemoryError ex)
57 
{
58
Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize
59
+ " minSideLength = " + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, ex);
60
return null;
61 
}
62 
}
63 
}
64
65
//} 
66
return b;
67
}
 1
//另外一处代码
 2
public static Bitmap getBitpMap(InputStream is)
 3 
{
 4 
ParcelFileDescriptor pfd;
 5
try
 6 
{
 7
pfd = getContentResolver().openFileDescriptor(uri, "r");
 8
} catch (IOException ex)
 9 
{
10
return null;
11 
}
12
java.io.FileDescriptor fd = pfd.getFileDescriptor();
13
BitmapFactory.Options options = new BitmapFactory.Options();
14
//先指定原始大小

15
options.inSampleSize = 1;
16
//只进行大小判断

17
options.inJustDecodeBounds = true;
18
//调用此方法得到options得到图片的大小

19
BitmapFactory.decodeFileDescriptor(fd, null, options);
20
//BitmapFactory.decodeStream(is, null, options);
21
//我们的目标是在800pixel的画面上显示。
22
//所以需要调用computeSampleSize得到图片缩放的比例

23
options.inSampleSize = computeSampleSize(options, 800);
24
//OK,我们得到了缩放的比例,现在开始正式读入BitMap数据

25
options.inJustDecodeBounds = false;
26
options.inDither = false;
27
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
28
29
//根据options参数,减少所需要的内存
30
//
Bitmap sourceBitmap = BitmapFactory.decodeFileDescriptor(fd, null, options);
31
Bitmap sourceBitmap = BitmapFactory.decodeStream(is, null, options);
32
return sourceBitmap;
33 
}
34
35
//这个函数会对图片的大小进行判断,并得到合适的缩放比例,比如2即1/2,3即1/3

36
static int computeSampleSize(BitmapFactory.Options options, int target)
37 
{
38
int w = options.outWidth;
39
int h = options.outHeight;
40
int candidateW = w / target;
41
int candidateH = h / target;
42
int candidate = Math.max(candidateW, candidateH);
43
if (candidate == 0)
44
return 1;
45
if (candidate > 1)
46 
{
47
if ((w > target) && (w / candidate) < target)
48
candidate -= 1;
49 
}
50
if (candidate > 1)
51 
{
52
if ((h > target) && (h / candidate) < target)
53
candidate -= 1;
54 
}
55
//if (VERBOSE)
56
Log.v(TAG, "for w/h " + w + "/" + h + " returning " + candidate + "(" + (w / candidate) + " / " + (h / candidate));
57
return candidate;
58
}

 

转载于:https://www.cnblogs.com/jevan/archive/2012/07/05/2577942.html

最后

以上就是儒雅金针菇为你收集整理的Android加载大图片OOM异常解决的全部内容,希望文章能够帮你解决Android加载大图片OOM异常解决所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部