【OOM】Android加载大图片OOM异常解决
16lz
2022-06-17
1、手动干涉dalvik的堆内存处理效率:
private final static float TARGET_HEAP_UTILIZATION = 0.75f; //for same activity public void onCreate() { ………… VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); ………… }
2、手动指定Android堆大小:
private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ; //for same activity public void onCreate() { ………… VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。当然对于内存吃紧来说还可以通过手动干涉GC去处理 ………… }
3、手动指定回收内存,指定gc:
1 if(bitmap!=null && !bitmap.isRecycled())2 {3 bitmap.recycle();4 System.gc();5 }
4、图片必须进行缩放,不然多半会出OOM:
/** * @param url * 图片的url * @param sc * ,显示的像素大小 * @return 返回指定RUL的缩略图 * * @author jevan 2012-7-3 * */ public static Bitmap loadImageFromUrl(String url, int sc) { URL m; InputStream i = null; BufferedInputStream bis = null; ByteArrayOutputStream out = null; if (url == null) return null; try { m = new URL(url); i = (InputStream) m.getContent(); bis = new BufferedInputStream(i, 1024 * 4); out = new ByteArrayOutputStream(); int len = 0; while ((len = bis.read(isBuffer)) != -1) { out.write(isBuffer, 0, len); } out.close(); bis.close(); } catch (MalformedURLException e1) { e1.printStackTrace(); return null; } catch (IOException e) { e.printStackTrace(); } if (out == null) return null; byte[] data = out.toByteArray(); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(data, 0, data.length, options); options.inJustDecodeBounds = false; int be = (int) (options.outHeight / (float) sc); if (be <= 0) { be = 1; } else if (be > 3) { be = 3; } options.inSampleSize = be; Bitmap bmp =null; try { bmp = BitmapFactory.decodeByteArray(data, 0, data.length, options); //返回缩略图 } catch (OutOfMemoryError e) { // TODO: handle exception MainActivity.print("Tile Loader (241) Out Of Memory Error " + e.getLocalizedMessage()); System.gc(); bmp =null; } return bmp; }
把上面几条全部用上,OOM的异常基本上能完全避免!!!
以下内容为转载,收藏。
//我们在BitmapManager.instance().decodeFile对图片进行解码,生成Bitmap的时候,我们会发现很多大图片会报OutOfMemoryError的错误,这个时候我们需要改变options里面的一些参数来解决这个问题,不然我们程序就跑不下去了。最简单的方法就是改变options.inSampleSize这个参数,把它增大,就可以解决很多图片OutOfMemoryError的问题。 //下面是一个使用了这个方式的代码 public static Bitmap makeBitmap(String path, int minSideLength, int maxNumOfPixels, BitmapFactory.Options options) { Bitmap b = null; Log.i(TAG, "makeBitmap : path = " + path); if (path == null) return null; File f = new File(path); //try { // b = BitmapManager.instance().decodeFile(f, null); //} catch (OutOfMemoryError ex) { // Log.e(TAG, "Got oom exception, we may try one more time, using Options:" + ex.getMessage()); if (options == null) { options = new BitmapFactory.Options(); } try { options.inJustDecodeBounds = true; BitmapManager.instance().decodeFile(f, options); if (options.mCancel || options.outWidth == -1 || options.outHeight == -1) { return null; } options.inSampleSize = computeSampleSize(options, minSideLength, maxNumOfPixels); options.inJustDecodeBounds = false; options.inDither = true; options.inPreferredConfig = null;//Bitmap.Config.ARGB_8888; b = BitmapManager.instance().decodeFile(f, options); } catch (OutOfMemoryError ex2) { Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize + " minSideLength = " + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, ex2); try { options.inSampleSize += 1; options.inJustDecodeBounds = false; options.inDither = true; options.inPreferredConfig = null; b = BitmapManager.instance().decodeFile(f, options); } catch (OutOfMemoryError e) { Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize + " minSideLength = " + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, e); try { options.inSampleSize += 1; options.inJustDecodeBounds = false; options.inDither = true; options.inPreferredConfig = null; b = BitmapManager.instance().decodeFile(f, options); } catch (OutOfMemoryError ex) { Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize + " minSideLength = " + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, ex); return null; } } } //} return b; }
//另外一处代码
public static Bitmap getBitpMap(InputStream is) { ParcelFileDescriptor pfd; try { pfd = getContentResolver().openFileDescriptor(uri, "r"); } catch (IOException ex) { return null; } java.io.FileDescriptor fd = pfd.getFileDescriptor(); BitmapFactory.Options options = new BitmapFactory.Options(); //先指定原始大小 options.inSampleSize = 1; //只进行大小判断 options.inJustDecodeBounds = true; //调用此方法得到options得到图片的大小 BitmapFactory.decodeFileDescriptor(fd, null, options); //BitmapFactory.decodeStream(is, null, options); //我们的目标是在800pixel的画面上显示。 //所以需要调用computeSampleSize得到图片缩放的比例 options.inSampleSize = computeSampleSize(options, 800); //OK,我们得到了缩放的比例,现在开始正式读入BitMap数据 options.inJustDecodeBounds = false; options.inDither = false; options.inPreferredConfig = Bitmap.Config.ARGB_8888; //根据options参数,减少所需要的内存 // Bitmap sourceBitmap = BitmapFactory.decodeFileDescriptor(fd, null, options); Bitmap sourceBitmap = BitmapFactory.decodeStream(is, null, options); return sourceBitmap; } //这个函数会对图片的大小进行判断,并得到合适的缩放比例,比如2即1/2,3即1/3 static int computeSampleSize(BitmapFactory.Options options, int target) { int w = options.outWidth; int h = options.outHeight; int candidateW = w / target; int candidateH = h / target; int candidate = Math.max(candidateW, candidateH); if (candidate == 0) return 1; if (candidate > 1) { if ((w > target) && (w / candidate) < target) candidate -= 1; } if (candidate > 1) { if ((h > target) && (h / candidate) < target) candidate -= 1; } //if (VERBOSE) Log.v(TAG, "for w/h " + w + "/" + h + " returning " + candidate + "(" + (w / candidate) + " / " + (h / candidate)); return candidate; }
更多相关文章
- java后台接收android客户端通过http方式发送的数据
- Android(安卓)网络图片查看器
- Android相机、图册demo
- android自定义ProgressBar
- Android(安卓)File Explorer 展示图片
- Android(安卓)图片缩放
- Android长按imageview把图片保存到本地
- android图片压缩 —— 2
- Jenkins持续集成安卓 Android