主要是本地图片的处理,后期会加上网络请求部分!慕课网hongyang大神讲解的
public class ImageLoader {
private static final String TAG = "ImageLoader";
private static ImageLoader mInstance;
/**
* 图片缓存的核心对象
*/
private LruCache<String,Bitmap> mLruCache;
/**
* 线程池
*/
private ExecutorService mThreadPool;
/**
* 线程池中默认的线程数量
*/
private static final int DEFAULT_THREAD_COUNT = 1;
/**
* 任务队列
*/
private LinkedList<Runnable> mTaskQueue;
/**
* 后台轮询线程
*/
private Thread mPoolThread;
private Handler mPoolThreadHandler;
//信号量 保证mPoolThreadHandler初始化完毕
private Semaphore mSemaphorePoolThreadHandler = new Semaphore(0);
private Semaphore mSemaphoreThreadPool;
/**
* UI线程中的Handler
*/
private Handler mUIHandler;
private Type mType = Type.LIFO;
//图片加载策略
public enum Type {
FIFO,LIFO
}
private ImageLoader(int threadCount,Type type){
init(threadCount, type);
}
private void init(int threadCount, Type type) {
//初始化线程池
mThreadPool = Executors.newFixedThreadPool(threadCount);
this.mType = type;
//初始化后台轮询线程
mPoolThread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
mPoolThreadHandler = new Handler(Looper.myLooper()){
@Override
public void handleMessage(Message msg) {
//处理后台轮询线程的消息
mThreadPool.execute(getTask());
try {
mSemaphoreThreadPool.acquire();
} catch (InterruptedException e) {
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) {
return value.getRowBytes() * value.getHeight();
}
};
mTaskQueue = new LinkedList<>();
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(){
if(mInstance == null){
synchronized (ImageLoader.class){
if(mInstance == null){
mInstance = new ImageLoader(DEFAULT_THREAD_COUNT,Type.LIFO);
}
}
}
return mInstance;
}
public static ImageLoader getInstance(int threadCount,Type type){
if(mInstance == null){
synchronized (ImageLoader.class){
if(mInstance == null){
mInstance = new ImageLoader(threadCount,type);
}
}
}
return mInstance;
}
/**
* 加载图片
* @param path
* @param imageView
*/
public void loadImage(final String path, final ImageView imageView){
imageView.setTag(path);
if(mUIHandler == null){
mUIHandler = new Handler(Looper.myLooper()){
@Override
public void handleMessage(Message msg) {
//处理图片
ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
Bitmap bitmap = holder.bitmap;
String path = holder.path;
ImageView iv = holder.imageView;
if(iv.getTag().toString().equals(path)){
iv.setImageBitmap(bitmap);
}
}
};
}
Bitmap bitmap = getBitmapFromLruCache(path);
if(bitmap != null){
refreshBitmap(path,imageView,bitmap);
} else {
addTasks(new Runnable(){
@Override
public void run() {
//加载图片并压缩
ImageSize imageSize = getImageSizeFromImageView(imageView);
Bitmap bitmap = decodeSampleBitmapFromPath(path,imageSize.width,imageSize.height);
//将图片加入缓存
addBitmapToLruCache(bitmap, path);
refreshBitmap(path,imageView,bitmap);
mSemaphoreThreadPool.release();
}
});
}
}
private void refreshBitmap(String path,ImageView imageView,Bitmap bitmap){
Message message = Message.obtain();
ImgBeanHolder holder = new ImgBeanHolder();
holder.bitmap = bitmap;
holder.imageView = imageView;
holder.path = path;
message.obj = holder;
mUIHandler.sendMessage(message);
}
private void addBitmapToLruCache(Bitmap bitmap, String path) {
if(getBitmapFromLruCache(path) == null){
if(path != null && bitmap != null){
mLruCache.put(path,bitmap);
}
}
}
/**
* 获取压缩图片
* @param path
* @param width
* @param height
* @return
*/
private Bitmap decodeSampleBitmapFromPath(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);
options.inJustDecodeBounds = false;
Log.i(TAG,options.inSampleSize+"");
return BitmapFactory.decodeFile(path,options);
}
/**
* 计算缩放比例
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/
private int caculateSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
int width = options.outWidth;
int height = options.outHeight;
int sampleSize = 1;
if( width > reqWidth || height > reqHeight){
int wScale = Math.round(width*1.0f/reqWidth);
int hScale = Math.round(height*1.0f/reqHeight);
sampleSize = Math.max(wScale,hScale);
}
return sampleSize;
}
/**
* 获取图片的尺寸
* @param imageView
* @return
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private ImageSize getImageSizeFromImageView(ImageView imageView) {
ImageSize imageSize = new ImageSize();
ViewGroup.LayoutParams lp = imageView.getLayoutParams();
DisplayMetrics displayMetrics = imageView.getContext().getResources().getDisplayMetrics();
int width = imageView.getWidth(); //获取imageview的实际宽度
if(width <= 0){
width = lp.width; //由于有可能imageview还没有生成显示出来,获取imageview在layout中的宽度
}
if(width <= 0){
width = imageView.getMaxWidth();
}
if(width <= 0){
width = displayMetrics.widthPixels;
}
int height = imageView.getHeight();
if(height <= 0){
height = lp.height;
}
if(height <= 0){
height = imageView.getMaxHeight();
}
if(height <= 0){
height = displayMetrics.heightPixels;
}
imageSize.height = height;
imageSize.width = width;
return imageSize;
}
private class ImageSize {
int width;
int height;
}
private synchronized void addTasks(Runnable runnable) {
mTaskQueue.add(runnable);
if(mPoolThreadHandler == null){
try {
mSemaphorePoolThreadHandler.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mPoolThreadHandler.sendEmptyMessage(0);
}
private Bitmap getBitmapFromLruCache(String path) {
return mLruCache.get(path);
}
private class ImgBeanHolder {
Bitmap bitmap;
String path;
ImageView imageView;
}
}