android 그림 불 러 오기 OOM (out of memory) 은 캐 시 크기 설정 을 지원 합 니 다. 더 이상 catch OOM 을 강제 하지 않 습 니 다.

http://blog.csdn.net/liaoxingliao/article/details/7168500
package l.test1.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;

public class BitmapUtil {
	private static final Size ZERO_SIZE = new Size(0,0);
	private static final Options OPTIONS_GET_SIZE = new Options();
	private static final Options OPTIONS_DECODE = new Options();
	
	static{
		OPTIONS_GET_SIZE.inJustDecodeBounds = true;
	}
	
	public static Size getBitMapSize(String path){
		File file = new File(path);
		if(file.exists()){
			InputStream in = null;
			try{
				in = new FileInputStream(file);
				BitmapFactory.decodeStream(in, null, OPTIONS_GET_SIZE);
				return new Size(OPTIONS_GET_SIZE.outWidth,OPTIONS_GET_SIZE.outHeight);
			} catch (FileNotFoundException e) {
				return ZERO_SIZE;
			}finally{
				closeInputStream(in);
			}
		}
		return ZERO_SIZE;
	}
	
	public static Bitmap createBitmap(String path,int width,int height){
		File file = new File(path);
		if(file.exists()){
			InputStream in = null;
			try {
				in = new FileInputStream(file);
				Size size = getBitMapSize(path);
				if(size.equals(ZERO_SIZE)){
					return null;
				}
				int scale = 1;
				int a = size.getWidth() / width;
				int b = size.getHeight() / height;
				scale = Math.max(a, b);
				synchronized (OPTIONS_DECODE) {
					OPTIONS_DECODE.inSampleSize = scale;
					Bitmap bitMap =  BitmapFactory.decodeStream(in,null,OPTIONS_DECODE);
					return bitMap;
				}
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} 
			finally{
				closeInputStream(in);
			}
		}
		return null;
	}
	
	public static void destory(Bitmap bitmap){
		if(null != bitmap && !bitmap.isRecycled()){
			bitmap.recycle();
			bitmap = null;
		}
	}
	
	private static void closeInputStream(InputStream in) {
		if(null != in){
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

class Size{
	private int width,height;
	Size(int width,int height){
		this.width = width;
		this.height = height;
	}
	public int getWidth() {
		return width;
	}
	public int getHeight() {
		return height;
	}
}
package l.test1.util;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import android.graphics.Bitmap;
/**
 * Bitmap   ,            ,      ,        Bitmap  
 *   :
 * 		         Bitmap   ,    Bitmap         
 * 		     ,              ,        
 * 		                    ,    
 * @author liaoxingliao
 *
 */
public final class BitMapLRU {
	
	private static int CACHE_BYTE_SIZE = 10*1024*1024; //  10M  
	
	private static int CACHE_SIZE = 2000; //       
	
	private static int byteSize = 0;
	
	private static final byte[] LOCKED = new byte[0];
	
	private static final LinkedList<String> CACHE_ENTRIES = 		//       Bitmap     ,            
			new LinkedList<String>(){
		private static final long serialVersionUID = 1L;
		@Override
		public void addFirst(String object) {
			while(remove(object));
			super.addFirst(object);
		}
	};
	private static final Stack<QueueEntry> TASK_QUEUE = new Stack<QueueEntry>();		//           
	private static final Set<String> TASK_QUEUE_INDEX = new HashSet<String>();				//             key,               
	private static final Map<String,Bitmap> IMG_CACHE_INDEX = new HashMap<String,Bitmap>();	//  Bitmap       ,    
	
	static{
//		         ,     
		new Thread(){
			{setDaemon(true);}
			public void run() {
				while(true) {
					synchronized (TASK_QUEUE) {
						if(TASK_QUEUE.isEmpty()) {
							try {
								TASK_QUEUE.wait();
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
					}
					QueueEntry entry = TASK_QUEUE.pop();
					String key = createKey(entry.path,entry.width,entry.height);
					TASK_QUEUE_INDEX.remove(key);
					createBitmap(entry.path, entry.width, entry.height);
				}
			}
		}.start();
	}
	
	/**
	 *                 ,        ,          ,     
	 *   ,  ,           ,      , ,    ,    
	 * @param path			       (       ,       )
	 * @param width			     
	 * @param height		     
	 * @return
	 */
	public static Bitmap createBitmap(String path, int width, int height) {
		Bitmap bitMap = null;
		try{
			while(CACHE_ENTRIES.size() >= CACHE_SIZE || byteSize >= CACHE_BYTE_SIZE) {
				destoryLast();
			}
			bitMap = useBitmap(path, width, height);
			if( bitMap != null && !bitMap.isRecycled()){
				return bitMap;//4294967296

			}
			bitMap = BitmapUtil.createBitmap(path, width, height);
			if(bitMap == null) {  //         ..
				return null; 
			}
			byteSize += (bitMap.getRowBytes() * bitMap.getHeight());
			
			String key = createKey(path,width,height);
			synchronized (LOCKED) {
				IMG_CACHE_INDEX.put(key, bitMap);
				CACHE_ENTRIES.addFirst(key);
			}
		}catch(OutOfMemoryError err) {
			System.out.println("OOM:" + byteSize);
			destoryLast();
			return createBitmap(path, width, height);
		}
		return bitMap;
	}
	
	/**
	 *                ,     
	 * @param size
	 */
	public static void setCacheSize(int size) {
		if(size <=0 ){
			throw new RuntimeException("size :"+size);
		}
		while(size < CACHE_ENTRIES.size()){
			destoryLast();
		}
		CACHE_SIZE = size;
	}
	
	/**
	 *                  
	 * @param path			    (  )
	 * @param width			    
	 * @param height		    
	 */
	public static void addTask(String path, int width, int height) {
		QueueEntry entry = new QueueEntry();
		entry.path = path;
		entry.width = width;
		entry.height = height;
		synchronized (TASK_QUEUE) {
			while(TASK_QUEUE.size() > 20) {
				QueueEntry e =  TASK_QUEUE.lastElement();
				TASK_QUEUE.remove(e);
				TASK_QUEUE_INDEX.remove(createKey(e.path, e.width, e.height));
			}
			String key = createKey(path,width,height);
			if(!TASK_QUEUE_INDEX.contains(key) && !IMG_CACHE_INDEX.containsKey(key)){
				TASK_QUEUE.push(entry);
				TASK_QUEUE_INDEX.add(key);
				TASK_QUEUE.notify();
			}
		}
	}
	
	public static void cleanTask() {
		synchronized (TASK_QUEUE) {
			TASK_QUEUE_INDEX.clear();
			TASK_QUEUE.clear();
		}
	}
	
	//         
	private static Bitmap useBitmap(String path,int width,int height) {
		Bitmap bitMap = null;
		String key = createKey(path,width,height);
		synchronized (LOCKED) {
			bitMap = IMG_CACHE_INDEX.get(key);
			if(null != bitMap){
				CACHE_ENTRIES.addFirst(key);
			}
		}
		return bitMap;
	}
	
	//         
	private static void destoryLast() {
		synchronized (LOCKED) {
			if(!CACHE_ENTRIES.isEmpty()) {
				String key = CACHE_ENTRIES.removeLast();
				if(key.length() > 0) {
					Bitmap bitMap = IMG_CACHE_INDEX.remove(key);
					if(bitMap != null) {
						bitMap.recycle();
						byteSize -= (bitMap.getRowBytes() * bitMap.getHeight());
						bitMap = null;
					}
				}
			}
		}
	}
	
	//    
	private static String createKey(String path,int width,int height) {
		if(null == path || path.length() == 0) {
			return "";
		}
		return path+"_"+width+"_"+height;
	}

	//         
	static class QueueEntry{
		public String path;
		public int width;
		public int height;
	}
}

좋은 웹페이지 즐겨찾기