图片加载的优化 --- 实现图片的缓存、本地内存及网络的三重筛选之后的加载

package com.dusk.lin.biz;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.util.Log;
import android.widget.ImageView;

import com.dusk.lin.constant.MConstant;
/**
 * @author Dusk
 * @version 1.0
 * 
 * */
public class ImageLoaderBiz {
	
	//定义出一个LruCache作为第一重图片数据的加载源:String 图片的网络路径作为key,  bitmap 图片作为值
	private static LruCache<String, Bitmap> lruCache;
	static{
		int cacheSize = 1024*1024*4;
		lruCache = new LruCache<String, Bitmap>(cacheSize ){
			@Override
			protected int sizeOf(String key, Bitmap value) {
				return value.getByteCount();
			}
		};
	}
	/**
	 * 该方法向外部直接返回指定网络路径的图片
	 * */
	public static Bitmap getImage(String imageUrl){
		Bitmap bitmap;
		if(imageUrl == null){
			Log.d("TAG:getimage", "imageUrl为空");
			return null;
		}
		//先判断LruCache中是否存在指定图片:存在返回该图片,不存在,向下刷选本地内存
		if((bitmap = getImageFromLruCache(imageUrl)) != null){
		return bitmap;
		}
		//判断手机内存中的Cache文件夹下是否缓存过指定图片:有,则返回该图片;没有,向下执行异步的网络图片下载
		if((bitmap = getImageFromCacheFile(imageUrl)) != null ){
			return bitmap;
		}
		//异步加载网络图片
		asyncGetImageByHttpURLConnection(imageUrl);
		return b;
	}
	
	/**
	 * 该方法可以直接设定指定imageview的src图片
	 * 
	 * */
	public static void setImage(String imageUrl, ImageView imageAvatar){
		Bitmap bitmap;
		if(imageUrl == null){
			Log.d("TAG:getimage", "imageUrl为空");
			return;
		}
		if((bitmap = getImageFromLruCache(imageUrl)) != null){
			imageAvatar.setImageBitmap(bitmap);
			return ;
		}
		if((bitmap = getImageFromCacheFile(imageUrl)) != null ){
			imageAvatar.setImageBitmap(bitmap);
			return ;
		}
		asyncGetImageByHttpURLConnection(imageUrl, imageAvatar);
	}
	
	
    private static void asyncGetImageByHttpURLConnection(String imageUrl,
			final ImageView imageAvatar) {
		new MyImageLoadAsyncTask(new ImageLoadAsyncListener() {
			
			@Override
			public void onImageLoadEnd(Bitmap bitmap) {
				imageAvatar.setImageBitmap(bitmap);
			}
		}).execute(imageUrl);
	}


	private static  Bitmap b = null;
	private static void asyncGetImageByHttpURLConnection(final String imageUrl) {
		new MyImageLoadAsyncTask(new ImageLoadAsyncListener() {
			
			@Override
			public void onImageLoadEnd(Bitmap bitmap) {
				b = bitmap;
			}
		}).execute(imageUrl);
	}
	
	protected static void saveImageToCacheFile(Bitmap b2, String path) {
		//拿到手机内存中的cache目录
		File fileCache = MConstant.context.getCacheDir();
		if(!fileCache.exists()){
			fileCache.mkdirs();
		}
		//文件名酌情而定
		String fileName = path.substring(path.indexOf("/")+1);
		File file = new File(fileCache, fileName);
		
		try {
			OutputStream out = new FileOutputStream(file);
			b2.compress(CompressFormat.JPEG, 100, out);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	private static class MyImageLoadAsyncTask extends AsyncTask<String, Void, Bitmap>{
        private ImageLoadAsyncListener listener;
        public MyImageLoadAsyncTask(ImageLoadAsyncListener listener) {
		    this.listener = listener;
        }
		@Override
		protected Bitmap doInBackground(String... params) {
			// TODO Auto-generated method stub
			Bitmap bitmap = null;
			String imageUrl = params[0];
			String path = MConstant.ROOT + imageUrl;
			URL url = null;
			InputStream in = null;
			HttpURLConnection conn = null;
			try {
				url= new URL(path);
				conn = (HttpURLConnection) url.openConnection();
				
				conn.setReadTimeout(5000);
				conn.setRequestMethod("GET");
				conn.setDoInput(true);
				conn.connect();
				
				int status = conn.getResponseCode();
				if(status == 200){
					in = conn.getInputStream();
					if(in != null){
						//先压缩图片
						bitmap = compressImage(in);
						//再分别在缓存和内存中备份
						lruCache.put(imageUrl, bitmap);
						saveImageToCacheFile(bitmap, imageUrl);
					}else{
						Log.e("TAG:imageloadByAsync", "数据库响应数据流为空");
					}
				}else{
					Log.e("TAG:imageloadByAsync", "数据库响应异常:"+status);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}finally{
				conn.disconnect();
				if(in != null){
					in = null;
				}
			}
			return bitmap;
		}
		
		@Override
		protected void onPostExecute(Bitmap result) {
			super.onPostExecute(result);
			listener.onImageLoadEnd(result);
		}
	}
	
	public interface ImageLoadAsyncListener{
		public void onImageLoadEnd(Bitmap bitmap);
	}

	private static Bitmap getImageFromCacheFile(String imageUrl) {
		String fileName = imageUrl.substring(imageUrl.lastIndexOf("/")+1);
		Bitmap bitmap = null;
		File cacheFile = MConstant.context.getCacheDir();
		if(cacheFile != null){
			File[] files = cacheFile.listFiles();
			for(File f : files){
				if(f.isFile() && f.getName().equals(fileName)){
					bitmap  = BitmapFactory.decodeFile(f.getAbsolutePath());
				}
			}
		}else{
			Log.e("TAG:getImageFromCacheFile", "cacheFile=null");
		}
		return bitmap;
	}

	public static Bitmap compressImage(InputStream in) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		int len = 0;
		byte[] buffer = new byte[1024];
		try {
			while((len = in.read(buffer)) != -1){
				baos.write(buffer, 0, len);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		byte[] data = baos.toByteArray();
		
		Options opts = new Options();
		opts.inJustDecodeBounds = true;
		BitmapFactory.decodeByteArray(data, 0, data.length, opts );
		
		int width = opts.outWidth;
		int height = opts.outHeight;
		
		int wCompress = 60;
		int hCompress = 60;
		
		int wScale = width/wCompress;
		int hScale = height/hCompress;
		
		int scale = Math.max(wScale, hScale);
		
		if(scale <= 0){
			scale = 1;
		}
		
		opts.inJustDecodeBounds = false;
		opts.inSampleSize = scale;
		
		return BitmapFactory.decodeByteArray(data, 0, data.length, opts);
	}

	private static Bitmap getImageFromLruCache(String imageUrl) {
		return  lruCache.get(imageUrl);
	}

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值