最近做android的項目,碰到一個下載圖片并顯示的需求篮绰,當下載的圖片較多時后雷,出現(xiàn)OutOfMemoryError的異常。
試了好多優(yōu)化方式吠各,最后發(fā)現(xiàn)是因為圖片比較大時臀突,bitmap分配內(nèi)存溢出問題。最后總結了一下走孽,優(yōu)化的方式有下面幾種:
1惧辈、不用的bitmap要及時回收銷毀
??? bitmap.recycle();bitmap= null;
2、顯示調(diào)用system.gc();觸發(fā)垃圾回收磕瓷,及時回收內(nèi)存盒齿。
3、stream轉(zhuǎn)換為bitmap時壓縮圖片質(zhì)量
??? 我的問題是BitmapFactory.decodeStream(stream)這個方法報的錯誤困食,錯誤信息是OutOfMemoryError边翁。
??? 也就是說stream轉(zhuǎn)換為bitmap的時候內(nèi)存不夠。下面是我的解決方案:
??? BitmapFactory.Options options = new BitmapFactory.Options();
??? options.inJustDecodeBounds = true;
??? Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
??? int imageHeight = options.outHeight;
??? int imageWidth = options.outWidth;
??? if(imageWidth > 200)
??? {
??????? int maxpix = imageHeight > imageWidth ? imageHeight : imageWidth;
??????? int scale = (int) (maxpix / 100);
??????? if (scale <= 0)
??????? {
??????????? scale = 1;
??????? }
??????? options.inSampleSize = scale;
??? }
??? options.inJustDecodeBounds = false;
??? stream = image.getImageViewInputStream(imageUrl);//重新讀取stream
??? bitmap = BitmapFactory.decodeStream(stream,null,options);
??? 屬性inJustDecodeBounds設置為true時,返回的bitmap為空硕盹,只是讀取圖片信息符匾,
??? 并不使用內(nèi)存讀取bitmap,當inJustDecodeBounds設置為false時,讀取bitmap,
??? 這之前必須重新讀一下stream。
4瘩例、壓縮圖片的其他方式
??? 1> 按寬高比縮放
??? public static Bitmap zoomImage(Bitmap bgimage, double newWidth,? double newHeight) {
??? // 獲取這個圖片的寬和高
??? float width = bgimage.getWidth();
??? float height = bgimage.getHeight();
??? // 創(chuàng)建操作圖片用的matrix對象
??? Matrix matrix = new Matrix();
??? // 計算寬高縮放率
??? float scaleWidth = ((float) newWidth) / width;
??? float scaleHeight = ((float) newHeight) / height;
??? // 縮放圖片動作
??? matrix.postScale(scaleWidth, scaleHeight);
??? Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width,
??? (int) height, matrix, true);
??? return bitmap;
??? }
2> 壓縮大小最大100k
??? public static Bitmap GetPressBitmap(Bitmap bitMap)
??? {
??? double maxSize = 100;
??? //將bitmap放至數(shù)組中啊胶,意在bitmap的大械楦鳌(與實際讀取的原文件要大)
??? ByteArrayOutputStream baos = new ByteArrayOutputStream();
??? bitMap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
??? byte[] b = baos.toByteArray();
??? //將字節(jié)換成KB
??? double mid = b.length/1024;
??? //判斷bitmap占用空間是否大于允許最大空間? 如果大于則壓縮 小于則不壓縮
??? if (mid > maxSize) {
??????? //獲取bitmap大小 是允許最大大小的多少倍
? ? ? ? double i = mid / maxSize;
?? ? ?? //開始壓縮? 此處用到平方根 將寬帶和高度壓縮掉
? ?? ?? //對應的平方根倍 (1.保持刻度和高度和原bitmap
? ?? ?? //比率一致,壓縮后也達到了最大大小占用空間的大醒嫫骸)
? ?? ?? bitMap = zoomImage(bitMap, bitMap.getWidth() / Math.sqrt(i),
? ?? ?? bitMap.getHeight() / Math.sqrt(i));
??? }
??? return bitMap;
??? }