package com.tarena.musicplayer.util;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.Semaphore;
import android.content.Context;
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.util.Log;
import android.widget.ImageView;
public class ImageLoader {
private static int threadCount;
private static ExecutorService exec;
private static Context context;
private static Handler uiHandler;
private static Handler pollHandler;
private static Thread pollThread;
private static LinkedBlockingDeque<Runnable> tasks;
private static LruCache<String, Bitmap> memCache;
private static boolean isFirst = true;
private static Semaphore pollLock;
private static Semaphore pollHandlerLock = new Semaphore(0);
/**
* ImageLoader的初始化方法
* 把上述所有属性都要进行赋值
* @param c
*/
public static void init(Context c){
if(!isFirst){
return;
}
isFirst = false;
context = c;
tasks = new LinkedBlockingDeque<Runnable>();
threadCount = getCoreNumbers();
pollLock = new Semaphore(threadCount);
exec = Executors.newFixedThreadPool(threadCount);
pollThread = new Thread(){
@Override
public void run() {
Looper.prepare();
pollHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
try {
Runnable task = tasks.getLast();
exec.execute(task);
pollLock.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
pollHandlerLock.release();
Looper.loop();
}
};
pollThread.start();
uiHandler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 101:
TaskBean bean = (TaskBean) msg.obj;
ImageView iv = bean.iv;
Bitmap bimtap = bean.bitmap;
String tag = bean.tag;
if(iv.getTag().toString().equals(tag)){
iv.setImageBitmap(bimtap);
}
break;
default:
super.handleMessage(msg);
break;
}
}
};
memCache = new LruCache<String, Bitmap>((int) (Runtime.getRuntime().maxMemory()/4)){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getHeight()*value.getRowBytes();
}
};
}
public static void loadImage(final ImageView iv,final String url){
Bitmap result = null;
final String tag = getMD5(url);
result = memCache.get(tag);
iv.setTag(tag);
if(result!=null){
Log.d("TAG","图片从内存缓存中加载");
iv.setImageBitmap(result);
return;
}
tasks.add(new Runnable() {
@Override
public void run() {
try{
URL u = new URL(url);
HttpURLConnection connection = (HttpURLConnection) u.openConnection();
connection.setDoInput(true);
connection.setRequestMethod("GET");
connection .connect();
InputStream in = connection.getInputStream();
Bitmap bitmap = compress(iv,in);
in.close();
memCache.put(tag, bitmap);
TaskBean bean = new TaskBean();
bean.bitmap = bitmap;
bean.iv = iv;
bean.tag = tag;
Message.obtain(uiHandler, 101, bean).sendToTarget();
pollLock.release();
}catch(Exception e){
e.printStackTrace();
}
}
});
if(pollHandler==null){
try {
pollHandlerLock.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Message.obtain(pollHandler).sendToTarget();
}
/**
* 根据ImageView的大小,对图像进行适当的压缩处理
* @param iv
* @param in
* @return
*/
protected static Bitmap compress(ImageView iv, InputStream in) {
try {
int width = iv.getWidth();
int height = iv.getHeight();
if(width==0||height==0){
width = context.getResources().getDisplayMetrics().widthPixels;
height = context.getResources().getDisplayMetrics().heightPixels;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
int len = -1;
while((len=in.read())!=-1){
out.write(len);
}
byte[] bytes = out.toByteArray();
out.close();
Options opts = new Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts );
int bitmapWidth = opts.outWidth;
int bitmapHeight = opts.outHeight;
int sampleSize = 1;
if(bitmapWidth*1.0/width>1||bitmapHeight*1.0/height>1){
sampleSize = (int) Math.ceil(Math.max(bitmapWidth*1.0/width, bitmapHeight*1.0/height));
}
opts.inSampleSize = sampleSize;
opts.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts);
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 把一个普通的字符串转成MD5格式的字符串
*
* @param str
* @return
*/
private static String getMD5(String str) {
StringBuffer sb = new StringBuffer();
try{
MessageDigest md = MessageDigest.getInstance("md5");
md.update(str.getBytes());
byte[] bytes = md.digest();
for (byte b : bytes) {
String temp = Integer.toHexString(b & 0xFF);
if(temp.length()==1){
sb.append("0");
}
sb.append(temp);
}
}catch(Exception e){
e.printStackTrace();
}
return sb.toString();
}
private static int getCoreNumbers() {
try {
File file = new File("/sys/devices/system/cpu/");
File[] files = file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
if(filename.contains("cpu")){
return true;
}
return false;
}
});
return files.length;
} catch (Exception e) {
e.printStackTrace();
return 1;
}
}
/**
* 持有bitmap,和要显示bitmap的imageView
* @author pjy
*
*/
private static class TaskBean{
Bitmap bitmap;
ImageView iv;
String tag;
}
/**
* 如果返回true,意味着ImageLoader尚未初始化
* 如果返回fasle,意味着ImageLoader初始化过了,不需要再次初始化了
* @return
*/
public static boolean isFirst(){
return isFirst;
}
}