题记 :在开发中,我们无法避免与各种imageView打交道,无论是ViewPage、RecycleView加载图片瀑布流等、头像的加载等。我想大家在与形形色色的图片打交道的过程中,一定遇到过这样的一个问题,在浏览界面时候,随便滑动了几下,app就非正常退出了,这很可能就是由于加载了bitmap,导致oom(out of memory)了。
那如何避免这种情况呢?我们在app开发中,可以从两个方向来处理这个问题,现在我们 先说说如何从资源端(图片上传部分)来尽可能的避免上述的问题;
*图片按比例大小压缩方法(根据路径获取图片并压缩)
/** * 图片按比例大小压缩方法(根据路径获取图片并压缩) * * @param srcPath 图片路径 * @return * @auther: AnJun * @create: 2017/2/22 */ private static Bitmap getImage(String srcPath) { BitmapFactory.Options newOpts = new BitmapFactory.Options(); newOpts.inJustDecodeBounds = true; newOpts.inPreferredConfig = Bitmap.Config.RGB_565; Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts); newOpts.inJustDecodeBounds = false; int width = newOpts.outWidth; int height = newOpts.outHeight; int reqHeight = 800; int reqWidth = 480; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } newOpts.inSampleSize = inSampleSize; bitmap = BitmapFactory.decodeFile(srcPath, newOpts); return compressImage(bitmap); }
* io流压缩方法,此处限定图片最大值
/** * io流压缩方法,此处限定图片最大值 * 这里限制不大于1000k * * @param image 资源图片 * @return * @auther: AnJun * @create: 2017/2/22 */ private static Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, baos); int options = 100; while (baos.toByteArray().length / 1024 > 1000) { options -= 10; baos.reset(); image.compress(Bitmap.CompressFormat.JPEG, options, baos); } ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray()); Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null); return bitmap; }
*随后,我们把获取到的bitmap存储到本地文件路径中
/** * 将压缩的bitmap保存到SDCard卡临时文件夹,用于上传 * * @param filename 图片路径 * @param bit 图片 * @return * @auther: AnJun * @create: 2017/2/22 */ private static String saveMyBitmap(String filename, Bitmap bit) { String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/LX_img/"; String filePath = baseDir + filename; File dir = new File(baseDir); if (!dir.exists()) { dir.mkdir(); } File f = new File(filePath); try { f.createNewFile(); FileOutputStream fOut = null; fOut = new FileOutputStream(f); bit.compress(Bitmap.CompressFormat.PNG, 100, fOut); fOut.flush(); fOut.close(); } catch (IOException e1) { e1.printStackTrace(); } return filePath; }
* 下面,我们加入了图片旋转角度判断/** * @auther: AnJun * @create: 2017/2/22 * 判断照片角度 */ public static int readPictureDegree(String path) { int degree = 0; try { ExifInterface exifInterface = new ExifInterface(path); int orientation = exifInterface.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: degree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = 270; break; } } catch (IOException e) { e.printStackTrace(); } return degree; }
* 随后旋转图片
/** * @auther: AnJun * @create: 2017/2/22 * 旋转照片 */ public static Bitmap rotateBitmap(Bitmap bitmap, int degress) { if (bitmap != null) { Matrix m = new Matrix(); m.postRotate(degress); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true); return bitmap; } return bitmap; }
* 获得图片旋转后的bitmap后,开始上传,并在上传成功后删除压缩后的bitmap
/** * 清除缓存文件 */ public static void deleteCacheFile() { File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/LX_img/"); RecursionDeleteFile(file); }
* 为了能全部删除,我们调用了递归删除/** * @auther: AnJun * @create: 2017/2/22 * 递归删除 */ private static void RecursionDeleteFile(File file) { if (file.isFile()) { file.delete(); return; } if (file.isDirectory()) { File[] childFile = file.listFiles(); if (childFile == null || childFile.length == 0) { file.delete(); return; } for (File f : childFile) { RecursionDeleteFile(f); } file.delete(); } }
下面我会附上项目中使用的bitmaputil工具类,希望能对大家有帮助。