package com.example.com.imageloader;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.LruCache;
import android.view.ViewGroup;
import android.widget.ImageView;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
-
Created by 61678 on 2016/6/29.
*/
public class ImageLoader {
private static ImageLoader imageLoader;
/**- 图片缓存核心
*/
private LruCache<String, Bitmap> mLrucache;
/** - 线程池
*/
private ExecutorService mThreadPool;
private static final int DEFAULT_THREAD_COUNT = 1;
/**
- 队列调度模式
*/
private Type type = Type.LIFO;
/** - 任务队列
*/
LinkedList<Runnable> mTAskQueue;
/** - 后台轮询线程
*/
Thread mPoolThread;
Handler mPoolThreadHandler;
Handler mUIHandler;
Semaphore semaphore = new Semaphore(0);
Semaphore semaphoreHandler;private enum Type {
LIFO, FIFO;
}public void loadImage(final String path, final ImageView imageView) {
imageView.setTag(path);
if (mUIHandler == null) {
mUIHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
//获取图片,为imageview设置图片
ImgBeanHold imgBeanHold = (ImgBeanHold) msg.obj;
Bitmap bitmap = imgBeanHold.bitmap;
String path = imgBeanHold.path;
ImageView imageView = imgBeanHold.imageView;if (imageView.getTag().toString().equals(path)) { imageView.setImageBitmap(bitmap); } } }; } Bitmap bitmap = getBitmapFromCache(path); if (bitmap != null) { refresh(path, imageView, bitmap); } else { addTast(new Runnable() { @Override public void run() { ImgSize size = getImgSize(imageView); Bitmap bm = decodeBitmap(path, size.width, size.hei); addLruCache(path, bm); refresh(path, imageView, bm); semaphoreHandler.release(); } }); }
}
private void refresh(String path, ImageView imageView, Bitmap bitmap) {
Message message = Message.obtain();
ImgBeanHold imgBeanHold = new ImgBeanHold();
imgBeanHold.bitmap = bitmap;
imgBeanHold.path = path;
imgBeanHold.imageView = imageView;
message.obj = imgBeanHold;
mUIHandler.sendMessage(message);
}private synchronized void addLruCache(String path, Bitmap bm) {
if (getBitmapFromCache(path) == null) {
if (bm != null) {
mLrucache.put(path, bm);
}
}
}private Bitmap decodeBitmap(String path, int width, int hei) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);options.inSampleSize = caculateSampleSize(options, width, hei); options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(path, options);
}
private int caculateSampleSize(BitmapFactory.Options options, int Rwidth, int Rhei) {
int wid = options.outWidth;
int hei = options.outHeight;int sampleSize = 1; if (wid > Rwidth hei > Rhei) { sampleSize = Math.max(Math.round(wid * 1.0f / Rwidth), Math.round(hei * 1.0f / Rhei)); } return sampleSize;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private ImgSize getImgSize(ImageView imageView) {
ImgSize size = new ImgSize();
DisplayMetrics metrics = imageView.getContext().getResources().getDisplayMetrics();ViewGroup.LayoutParams params = imageView.getLayoutParams(); int width = imageView.getWidth(); if (width <= 0) { width = params.width; } if (width <= 0) { width = imageView.getMaxWidth(); } if (width <= 0) { width = metrics.widthPixels; } int hei = imageView.getHeight(); if (hei <= 0) { hei = params.height; } if (hei <= 0) { hei = imageView.getMaxHeight(); } if (hei <= 0) { hei = metrics.heightPixels; } size.hei = hei; size.width = width; return size;
}
private class ImgSize {
int hei;
int width;
}private void addTast(Runnable runnable) {
mTAskQueue.add(runnable);
if (mPoolThreadHandler == null) {
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mPoolThreadHandler.sendEmptyMessage(1);
}private class ImgBeanHold {
Bitmap bitmap;
String path;
ImageView imageView;
}private Bitmap getBitmapFromCache(String path) {
return mLrucache.get(path);
}
private ImageLoader(int mThreadCount, Type type) {
init(mThreadCount, type);
}
private Runnable getTask() {
if (type == Type.LIFO) {
return mTAskQueue.removeLast();
}
if (type == Type.FIFO) {
return mTAskQueue.removeFirst();
}
return null;
}private void init(int mThreadCount, Type type) {
mPoolThread = new Thread() {
@Override
public void run() {
Looper.prepare();
mPoolThreadHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//线程池取出一个任务执行mThreadPool.execute(getTask()); try { semaphoreHandler.acquire(); } catch (InterruptedException e) { e.printStackTrace(); } } }; semaphore.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(); } }; //创建线程池 mThreadPool = Executors.newFixedThreadPool(mThreadCount); mTAskQueue = new LinkedList<>(); this.type = type; semaphoreHandler = new Semaphore(mThreadCount);
}
public static ImageLoader getImageLoader() {
if (imageLoader == null) {
synchronized (ImageLoader.class) {
if (imageLoader == null) {
imageLoader = new ImageLoader(DEFAULT_THREAD_COUNT, Type.LIFO);
}
}
}
return imageLoader;
}
} - 图片缓存核心