Android性能优化----图片三级缓存

当我们在app中加载大量的图片时,稍有不注意就容易出现OOM异常,为了避免出现这样的问题并保证好的用户的体验,做好缓存是非常重要,下面介绍如何为图片做三级缓存,所谓三级缓存是指在文件和内存中都做缓存,所需的数据首先从内存中做的缓存中取,当内存中没有缓存时再从文件中的缓存取,当文件中的缓存也没有时,就通过网络访问服务器取并在取到数据后,在内存和文件中都做一个缓存。

在内存中的缓存我们使用LruCache类来实现,它是一种强引用的缓存技术,它会保存最近有使用的数据,当缓存满时他会清除那些在近期没有使用的缓存数据。下面是具体的代码:

/**
 * 类功能:用三级缓存为ListView中的ImageView设置图片
 * @author Administrator
 *
 */
public class CacheLoadBitmap {
	private MainActivity context;
	private ExecutorService threadPool;
	//因为使用ListView来显示图片,所以每一项ImageView是复用的,为了避免图片显示的错位,使用url来标记应该显示的图片
	private Map<ImageView,String> threadMap=new HashMap<ImageView, String>();
	
	
	//这里获取系统可用的内存大小,并取八分之一来做LruCache的缓存大小,缓存的大小根据需要来定
	private int maxSize = (int) (Runtime.getRuntime().freeMemory() /8);
	//LruCache的构造器接收一个用于缓存字节数
	private LruCache<String,Bitmap> cache=new LruCache<String,Bitmap>(maxSize);
	
	public CacheLoadBitmap(MainActivity context){
		this.context=context;
		threadPool = Executors.newFixedThreadPool(6);
	}
	public void display(ImageView iv,String url){
		//先从内存取
		Bitmap bitmap=cache.get(url);
		if(bitmap!=null){
		
			iv.setImageBitmap(bitmap);
			Log.d("load","内存取");
			return;
		}
		//再从内存取
		File file=new File(context.getCacheDir(),Md5Utils.md5(url));	
		if (file != null  && file.exists()) {
			//文件存在
			//把文件转换成bitmap
			bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
			iv.setImageBitmap(bitmap);
			//再往内存写
			cache.put(url, bitmap);
			Log.d("load","文件取");
			return ;
		}
		//从网络取
		URL pic_url;
		try {
			pic_url = new URL(url);
			//刷新ImageView的url
			threadMap.put(iv, url);
			threadPool.submit(new LoadTask(pic_url, iv));
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Log.d("load","网络取");
		
		
	}
	private void saveBitmapToCacheFile(Bitmap bitmap,String url) {
		File file = new File(context.getCacheDir(),Md5Utils.md5(url));
		try {
			bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(file));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	private class LoadTask implements Runnable{
		private URL url;
		private ImageView iv;
		public LoadTask(URL url,ImageView iv){
			this.url=url;
			this.iv=iv;
		}
		@Override
		public void run() {
			// TODO Auto-generated method stub
			try {
				
				HttpURLConnection connection = (HttpURLConnection) url.openConnection();
				connection.setRequestMethod("GET");
				connection.setReadTimeout(8000);
				InputStream in = connection.getInputStream();
				final Bitmap bitmap=BitmapFactory.decodeStream(in);
				//1.存入内存缓存中
				cache.put(url.toString(), bitmap);
				//2.往本地文件缓存中添加
				saveBitmapToCacheFile(bitmap,url.toString());
				context.runOnUiThread(new Runnable() {
					
					@Override
					public void run() {
						// TODO Auto-generated method stub
						String newurl=threadMap.get(iv);
						//这里判断只有拥有最新url的图片才能显示,也就是在同一个ImageView上只有晚启动的网络图片获取线程所获取的图片才显示
						if(newurl.equals(url.toString()))
							iv.setImageBitmap(bitmap);
					}
				});
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
}


你可能感兴趣的:(Android性能优化----图片三级缓存)