android自带的处理Bitmap out Memory 的处理,我仅仅是改变了些写法成为自己用的东西
Posted jhcelue
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android自带的处理Bitmap out Memory 的处理,我仅仅是改变了些写法成为自己用的东西相关的知识,希望对你有一定的参考价值。
每天上万次的启动载入证明这个载入是不错的;
第三方的载入框架非常多,推荐使用成熟框架,比方大家都知道的ImageLoad等,
这里的仅仅供学习;
我也曾在一个菜谱的项目里写过载入手机相冊图片的,只是当时写的不好,有空我会再写一个,这个项目里用这个jar包,上万次的载入偶尔看到三星的报两三个OOM还好
缓存管理在这里
http://blog.csdn.net/intbird/article/details/38338713
图片处理在这里
http://blog.csdn.net/intbird/article/details/38338811
界面回收图片在这里
http://blog.csdn.net/intbird/article/details/19905549
工具Jar包在这里说明:
http://pan.baidu.com/s/1dDtOZbr
集成的一个[缓存和图片资源载入]工具类,BitmapHelper,CacheHelper,,
下载地址http://pan.baidu.com/s/1dDtOZbr
用法://注,必须导入android-support-v4包.
1,在应用初始化时初始化缓存文件夹:
//(sd下主目录,拍照目录,图片缓存目录)
//主文件夹一般为应用的getString()中的AppName;
CacheHelper.initCache("Intbird");
//经常使用的一些方法
2,初始化图片帮助类
BitmapHelper bitmapHelper=new BitmapHelper(context,R.drawable.ic_launcher,R.drawable.ic_launcher);
BitmapHelper bitmapHelper=new BitmapHelper(context);
//终于载入实现类
BitmapHelper.LoadOptions options=new BitmapHelper.LoadOptions();
//一些简单的图片处理的封装,在其它用到的地方在说明
3 外部帮助类,封装程序中遇到图片的地方
public static class ImageOptions implements Serializable{ public int imageType; public int cropWidth; public int cropHeight; public int displayWidth; public int displayHeight; public int qulity; public int maxKb=-1; public boolean isNeedRoteAnge=false; public boolean isTumbnail; public ImageUploadType uploadType; public ImageCropType cropType; //已知载入方法 public LoadBitmapFinish finish; public DisplayImageOptions displayOption; public ImageLoadingListener listener; }
4,普通快捷记载单个图片
bitmapHelper.loadBitmap(BitmapHelper.IMG_TYPE_FILE, fileUrl, iv,options.displayWidth,options.displayHeight,options.finish);
//内部真实实现方式,能够构造这个很多其它的功能
bitmapHelper.loadBitmap(loadOption);
//finish
LoadBitmapFinish 在失败和成功后都会返回,失败时bitmap返回为空
5,对于列表载入实现
//在载入的前面加个true,means is used in listView;
bitmap.loadBitmap(true,BitmapHelper.IMG_TYPE_WEB, value, v,200,200,null);
//内部真实实现方式,能够构造这个很多其它的功能
bitmapHelper.loadBitmap(loadOption);
6,演示样例
//单个
bitmapHelper.loadBitmap(BitmapHelper.IMG_TYPE_FILE, fileUrl, iv,options.displayWidth,options.displayHeight,options.finish);
//列表
@Override public void setViewImage(ImageView v, String value) { <span style="white-space:pre"> </span>bitmap.loadBitmap(true,BitmapHelper.IMG_TYPE_WEB, value, v,200,200,null); }
//停止载入
if(bitmap!=null)
bitmap.finishLoadForList();
}
7,载入效果
1.0.0大致实现方式:版本号已经过多次改动和项目中不同手机收集到的错误信息改动过,请使用云盘上最新的版本号以保证项目能够正常使用(最新的是我在项目里使用的),下面代码仅供学习....
/** * @author [email protected] * @time 20140606 */ package com.intbird.utils; import java.lang.ref.WeakReference; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.media.ThumbnailUtils; import android.os.AsyncTask; import android.widget.ImageView; public class BitmapHelper { private CacheManager cacheManager; public static final int IMG_TYPE_RES=0; public static final int IMG_TYPE_WEB=1; public static final int IMG_TYPE_FILE=3; private Bitmap bmpHolder=null; private Bitmap bmpNoImg=null; public BitmapHelper(Context context,int loadingId,int loadNoId){ cacheManager=CacheManager.getInstance(); bmpHolder=BitmapFactory.decodeResource(context.getResources(),loadingId); bmpNoImg=BitmapFactory.decodeResource(context.getResources(),loadNoId); } /** * 载入图片 * @param type 网络文件,本地文件,还是资源文件 * @param fileUrl url * @param imageView 控件 * @param width 要获取的指定高度 * @param height 要获取的指定宽度 */ public void commonLoadBitmap(int type,String fileUrl,ImageView imageView,int width,int height){ //内存和文件里没有图片,又一次获取; Bitmap bmp=cacheManager.getBitmapFromCache(fileUrl); if(bmp!=null){ imageView.setImageBitmap(bmp); } else{ switch(type){ case IMG_TYPE_WEB: loadMultiBitmapFromWeb(fileUrl, imageView,width,height); break; case IMG_TYPE_FILE: imageView.setImageBitmap(getBitmapFormFile( fileUrl, width, height, true)); break; case IMG_TYPE_RES: imageView.setImageResource(Integer.parseInt(fileUrl)); break; } } } /** * 设置ImageView为获取指定文件地址的指定高度指定宽度的图片; * @param fileUrl 文件地址 * @param reqWidth 目标宽度 * @param reqHeight 目标高度 * @return bitmap */ public Bitmap loadSingleBitmapFromFile(String fileUrl,ImageView iv,int reqWidth,int reqHeight){ BitmapFactory.Options options=new BitmapFactory.Options(); options.inJustDecodeBounds=true; options.inSampleSize=calculateInSampleSize(options, reqWidth, reqHeight); BitmapFactory.decodeFile(fileUrl,options); options.inJustDecodeBounds=false; Bitmap bmp=BitmapFactory.decodeFile(fileUrl,options); if(iv!=null) iv.setImageBitmap(bmp); return bmp; } /** * 设置ImageView为须要载入的一张网络图片; * @param webUrl * @param imageView * @param width * @param heigth */ public void loadSingleBitmapFromWeb(String webUrl,ImageView imageView,int width,int heigth){ BitmapHelper.BitmapWorkerSingleTask task=new BitmapWorkerSingleTask(imageView); task.execute(webUrl,width+"",heigth+""); } /** * adapter中载入图片 * @param fileUrl 图片地址 * @param imageView 图片控件 * @param width 要得到的宽度 * @param height 要的到的高度 */ public void loadMultiBitmapFromWeb(String fileUrl, ImageView imageView,int width,int height) { if (cancelPotentialWork(fileUrl, imageView)) { final BitmapMultiWorkerTask task = new BitmapMultiWorkerTask(imageView); final AsyncDrawable asyncDrawable =new AsyncDrawable(bmpHolder, task); imageView.setImageDrawable(asyncDrawable); task.execute(fileUrl,width+"",height+""); } } /** * 从网络中载入一个须要的Bitmap; * @param webUrl * @param reqWidth * @param reqHeight * @return */ public Bitmap getBitmapFormWeb(String webUrl,int reqWidth,int reqHeight){ BitmapFactory.Options options=new BitmapFactory.Options(); options.inJustDecodeBounds=true; options.inSampleSize=calculateInSampleSize(options, reqWidth, reqHeight); return ConnInternet.loadBitmapFromNet(webUrl, options); } /** * 将图片文件转换成bitmap * * @param fileUrl * 图片文件路径 * @param width * 宽度 * @param height * 高度 * @param isThumbnail * 是否依据高宽生成缩略图 * @return */ public Bitmap getBitmapFormFile(String fileUrl, int width, int height, boolean isThumbnail) { Bitmap bitmap=loadSingleBitmapFromFile(fileUrl,null, width, height); // 生成固定尺寸的缩略图 if (isThumbnail) { bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height, ThumbnailUtils.OPTIONS_RECYCLE_INPUT); } cacheManager.addBitmapToCache(fileUrl, bitmap); return bitmap; } /** * 转换图片成圆形 * * @param bitmap * @return */ public static Bitmap changeBitmapToRound(Bitmap bitmap) { if(bitmap==null) return null; int width = bitmap.getWidth(); int height = bitmap.getHeight(); float roundPx; float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom; if (width <= height) { roundPx = width / 2; left = 0; top = 0; right = width; bottom = width; height = width; dst_left = 0; dst_top = 0; dst_right = width; dst_bottom = width; } else { roundPx = height / 2; float clip = (width - height) / 2; left = clip; right = width - clip; top = 0; bottom = height; width = height; dst_left = 0; dst_top = 0; dst_right = height; dst_bottom = height; } Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect src = new Rect((int) left, (int) top, (int) right, (int) bottom); final Rect dst = new Rect((int) dst_left, (int) dst_top, (int) dst_right, (int) dst_bottom); paint.setAntiAlias(true);// 设置画笔无锯齿 canvas.drawARGB(0, 0, 0, 0); // 填充整个Canvas paint.setColor(color); // 下面有两种方法画圆,drawRounRect和drawCircle // canvas.drawRoundRect(rectF, roundPx, roundPx, paint);// // 画圆角矩形,第一个參数为图形显示区域。第二个參数和第三个參数各自是水平圆角半径和垂直圆角半径。 canvas.drawCircle(roundPx, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));// 设置两张图片相交时的模式,參考http://trylovecatch.iteye.com/blog/1189452 canvas.drawBitmap(bitmap, src, dst, paint); // 以Mode.SRC_IN模式合并bitmap和已经draw了的Circle return output; } /** * 计算所需大小的图片 的压缩比例 * @param options * @param reqWidth 所需宽度 * @param reqHeight 所需高度 * @return 压缩比例 */ public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; } /** * 检查启动的任务 * @param fileUrl 文件路径 * @param imageView 目标控件 * @return 是否開始载入任务 */ private boolean cancelPotentialWork(String fileUrl, ImageView imageView) { final BitmapMultiWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (bitmapWorkerTask != null) { String bitmapUrl = bitmapWorkerTask.fileUrl; if (bitmapUrl!=null&&bitmapUrl != fileUrl) { bitmapWorkerTask.cancel(true); return true; } else { return false; } } return true; } /** * 获取该图片控件中的载入任务 * @param imageView * @return 返回该任务 */ private BitmapMultiWorkerTask getBitmapWorkerTask(ImageView imageView) { if (imageView != null) { final Drawable drawable = imageView.getDrawable(); if (drawable instanceof AsyncDrawable) { final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; return asyncDrawable.getBitmapWorkerTask(); } } return null; } private class AsyncDrawable extends BitmapDrawable { private final WeakReference<BitmapMultiWorkerTask> bitmapWorkerTaskReference; @SuppressWarnings("deprecation") public AsyncDrawable(Bitmap bitmap,BitmapMultiWorkerTask bitmapWorkerTask) { super(bitmap); bitmapWorkerTaskReference =new WeakReference<BitmapMultiWorkerTask>(bitmapWorkerTask); } public BitmapMultiWorkerTask getBitmapWorkerTask() { return bitmapWorkerTaskReference.get(); } } private class BitmapMultiWorkerTask extends AsyncTask<String, Void, Bitmap> { private WeakReference<ImageView> imageViewReference; private String fileUrl; public BitmapMultiWorkerTask(ImageView imageView){ imageViewReference=new WeakReference<ImageView>(imageView); } @Override protected Bitmap doInBackground(String... params) { fileUrl=params[0]; int reqWidth=Integer.valueOf(params[1]); int reqHeight=Integer.valueOf(params[2]); Bitmap bitmap=getBitmapFormWeb(fileUrl,reqWidth,reqHeight); return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { if (isCancelled()) { bitmap = null; } if (imageViewReference != null) { final ImageView imageView = imageViewReference.get(); final BitmapMultiWorkerTask bitmapWorkerTask =getBitmapWorkerTask(imageView); if (this == bitmapWorkerTask && imageView != null) { if(bitmap!=null){ imageView.setImageBitmap(bitmap); cacheManager.addBitmapToCache(fileUrl, bitmap); } else{ imageView.setImageBitmap(bmpNoImg); } } } } } /** * 异步载入一张图片 * @author [email protected] * */ private class BitmapWorkerSingleTask extends AsyncTask<String, Void, Bitmap>{ private WeakReference<ImageView> imageViewReference; private String fileUrl=""; public BitmapWorkerSingleTask(ImageView imageView){ imageViewReference=new WeakReference<ImageView>(imageView); } @Override protected Bitmap doInBackground(String... params) { fileUrl=params[0]; int reqWidth=Integer.valueOf(params[1]); int reqHeight=Integer.valueOf(params[2]); Bitmap bitmap=getBitmapFormWeb(fileUrl,reqWidth,reqHeight); return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { if (imageViewReference != null) { final ImageView imageView = imageViewReference.get(); if (imageView != null) { if(bitmap!=null){ imageView.setImageBitmap(bitmap); } else{ imageView.setImageBitmap(bmpNoImg); } } } } } }
以上是关于android自带的处理Bitmap out Memory 的处理,我仅仅是改变了些写法成为自己用的东西的主要内容,如果未能解决你的问题,请参考以下文章
Android知识要点整理----Bitmap图片处理和展示
Android手动回收bitmap,引发Canvas: trying to use a recycled bitmap处理