图片加载类ImageLoader
2015-12-14 17:33
253 查看
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; } }
相关文章推荐
- Android设计模式
- 关于mybatis中基本类型条件判断问题
- apxs动态安装扩展模块
- rsync启动脚本
- 自定义UINavigationItem的两种方法以及相应的隐藏方法
- linux 定时执行shell脚本 定时任务
- 权限“Permission is only granted to system apps”错误
- PHP Fatal error: Call-time pass-by-reference has been removed
- sublime text3 自动编译php 适合用于简单的php文件执行
- PopupWindow的简单使用
- java代码获取jdbc链接properties
- kill及kill -9的用法及如何实现进程的优雅退出
- 老李分享:系统可用性评估
- Android动画学习笔记-Android Animation
- Maven - 【日常问题】
- 画板开发问题
- sqliteDataBase 到底是不是线程安全的
- bzoj-1834 network 网络扩容 【网络流】
- 实时公交位置系统的实现
- SVN用户及权限配置