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);
}
	

//停止载入

bitmapHelper.finishLoadSingle();//单个
adapter.finishLoad();//列表

public void finishLoad(){
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类

Android知识要点整理----Bitmap图片处理和展示

Android手动回收bitmap,引发Canvas: trying to use a recycled bitmap处理

Android Bitmap深入介绍---基础

Android Bitmap