图片加载类ImageLoader

import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v4.util.LruCache;
import android.support.v4.view.ViewPager.LayoutParams;
import android.util.DisplayMetrics;
import android.widget.ImageView;

//图片加载类
public class ImageLoader {
	private static ImageLoader mInstance;
	//图片缓存的核心对象
	private LruCache<String, Bitmap> mLruCache;
	//线程池
	private ExecutorService mThreadPool;
	private static final int DEAFULT_THREAD_COUNT=1;
	//队列的调度方式
	private Type mType =Type.LIFO;
	//任务队列
	private LinkedList<Runnable> mTaskQueue;
	//后台轮询线程
	private Thread mPoolThread;
	private Handler mPoolThreadHandler;
	//UI线程中的Handler
	private Handler mUIHandler;
	
	private Semaphore mSemaphorePoolThreadHandler =new Semaphore(0);
	
	private Semaphore mSemaphoreThreadPool;
	public enum Type{
		FIFO,LIFO;
		}
	
	
	private ImageLoader(int threadCount,Type type){
		init(threadCount,type);
	}
	
	//初始化
	private void init(int threadCount, Type type) {
		//后台轮询线程
		mPoolThread=new Thread(){
			public void run(){
				Looper.prepare();
				mPoolThreadHandler =new Handler(){
					@Override
					public void handleMessage(Message msg) {
						//线程池取出一个任务进行执行
						mThreadPool.execute(getTask());
						
						try {
							mSemaphoreThreadPool.acquire();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						
					}

					
				};
				//释放一个信号量
				mSemaphorePoolThreadHandler.release();
				Looper.loop();
			}
		};
		mPoolThread.start();
		//获取我们应用的最大可用内存
		int maxMemory =(int) Runtime.getRuntime().maxMemory();
		int cacheMemory =maxMemory/8;
		
		mLruCache =new LruCache<String, Bitmap>(cacheMemory){
			@Override
			protected int sizeOf(String key, Bitmap value) {
				// TODO Auto-generated method stub
				return value.getRowBytes()*value.getHeight();
			}
		};
		//创建线程池
		mThreadPool =Executors.newFixedThreadPool(threadCount);
		mTaskQueue =new LinkedList<Runnable>();
		mType = type;
		
		mSemaphoreThreadPool =new Semaphore(threadCount);
	}
	//从任务队列取出一个方法
	private Runnable getTask() {
		if(mType == Type.FIFO){
			return mTaskQueue.removeFirst();
		}else if(mType == Type.LIFO){
			return mTaskQueue.removeLast();
		}
		return null;
	}

	public static ImageLoader getInstance(int i, Type lifo){
		if(mInstance == null){
			synchronized (ImageLoader.class) {
				if(mInstance == null){
					mInstance = new ImageLoader(DEAFULT_THREAD_COUNT,Type.LIFO);
				}
			}
		}
		return mInstance;
	}
	//根据path为imageview设置图片
	public void loadImage(final String path, final ImageView imageView){
		imageView.setTag(path);
		if(mUIHandler==null){
			mUIHandler =new Handler(){
				@Override
				public void handleMessage(Message msg) {
					//获取得到的图片,为imageView的、回调设置图片
					ImgBeanHolder holder =(ImgBeanHolder) msg.obj;
					Bitmap bm =holder.bitmap;
					ImageView imageView = holder.imageView;
					String  path =holder.path;
					//将path与getTag存储路径进行比较
					if(imageView.getTag().toString().equals(path)){
						imageView.setImageBitmap(bm);
					}
				}
			};
			
		}
		//根据path在缓存中获取bitmap
				Bitmap bm =getBitmapFromLruCache(path);
				
				if(bm!=null){
					reflash(path, imageView, bm);
				}else{
					addTasks(new Runnable() {
						
						@Override
						public void run() {
							//加载图片
							//图片的压缩
							//1.获取图片所需要的大小
							ImageSize imageSize=getImageViewSize(imageView);
							//2.压缩图片
							Bitmap bm=decodeSamledBitmapFromPath(path,imageSize.width,imageSize.height);
							//3.把图片加入到缓存
							addBitmapToLruCache(path,bm);
							
							reflash(path, imageView, bm);
							
							mSemaphoreThreadPool.release();
						}

						
					});
				}
		
	}
	private void reflash(String path, ImageView imageView,
			Bitmap bm) {
		Message message =Message.obtain();
		ImgBeanHolder holder =new ImgBeanHolder();
		holder.bitmap=bm;
		holder.path=path;
		holder.imageView=imageView;
		message.obj=holder;
		mUIHandler.sendMessage(message);
	}
	//将图片加入缓存
	protected void addBitmapToLruCache(String path, Bitmap bm) {
		if(getBitmapFromLruCache(path)==null){
			if(bm!=null){
				mLruCache.put(path, bm);
			}
		}
		
	}

	//根据图片需要显示的宽和高对图片进行压缩
	protected Bitmap decodeSamledBitmapFromPath(String path, int width,
			int height) {
		//获取图片的宽和高,并不把图片加载到内存中
		BitmapFactory.Options options =new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, options);
		options.inSampleSize =caculateSampleSize(options,width,height);
		//使用获取到的simplesize再次解析图片
		options.inJustDecodeBounds=false;
		Bitmap bitmap=BitmapFactory.decodeFile(path, options);
		return bitmap;
	}
	//根据需求的宽和高以及图片实际的宽高计算SampleSize
	private int caculateSampleSize(Options options, int reqWidth, int reqHeight) {
		int width= options.outWidth;
		int height =options.outHeight;
		
		int inSampleSize=1;
		
		if(width>reqWidth||height>reqHeight){
			int widthRadio =Math.round(width*1.0f/reqWidth);
			int heightRadio =Math.round(height*1.0f/reqHeight);
			
			inSampleSize =Math.max(widthRadio, heightRadio);
			
		}
		
		return inSampleSize;
	}

	//根据ImageView获取适当的压缩的宽和高
	protected ImageSize getImageViewSize(ImageView imageView) {
		ImageSize imageSize =new ImageSize();
		
		DisplayMetrics displayMetrics = imageView.getContext().getResources().getDisplayMetrics();
		android.view.ViewGroup.LayoutParams lp =imageView.getLayoutParams();
		//int width =(lp.width == LayoutParams.WRAP_CONTENT?0:imageView.getWidth());
		int width=imageView.getWidth();//获取imageview的实际宽度
		if(width<=0){
			width =lp.width;//获取imageview在layout中声明的宽度
		}
		if(width<=0){
			width=getImageViewFieldValue(imageView, "mMaxWidth");//检查最大值
		}
		if(width<=0){
			width=displayMetrics.widthPixels;
		}
		
		int height=imageView.getHeight();//获取imageview的实际宽度
		//int height =getImageViewFieldValue(imageView, "mMaxHeight");
		if(height<=0){
			width =lp.height;//获取imageview在layout中声明的宽度
		}
		if(height<=0){
			height=getImageViewFieldValue(imageView, "mMaxHeight");//检查最大值
		}
		if(width<=0){
			height=displayMetrics.heightPixels;
		}
		
		imageSize.width =width;
		imageSize.height=height;
		return imageSize;
		
	}
	//通过反射获取imageview的某个属性值
	private static int getImageViewFieldValue(Object object,String fieldName){
		int value=0;
		try {
		Field field =ImageView.class.getDeclaredField(fieldName);
		field.setAccessible(true);
		
		
			int fieldValue =field.getInt(object);
			if(fieldValue>0&&fieldValue<Integer.MAX_VALUE){
				value=fieldValue;
			}
		}  catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return value;
	}

	private synchronized void addTasks(Runnable runnable) {
		mTaskQueue.add(runnable);
		try {
			if(mPoolThreadHandler==null)
			mSemaphorePoolThreadHandler.acquire();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		mPoolThreadHandler.sendEmptyMessage(0x110);
		
	}

	//根据path在缓存中获取bitmap
	private Bitmap getBitmapFromLruCache(String key) {
		
		return mLruCache.get(key);
	}
	private class ImageSize{
		int width;
		int height;
	}
	
	private class ImgBeanHolder{
		Bitmap bitmap;
		ImageView imageView;
		String path;
	}
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值