Android编程图片加载类ImageLoader定义与用法实例分析

Android编程图片加载类ImageLoader定义与用法实例分析,第1张

概述本文实例讲述了Android编程图片加载类ImageLoader定义与用法。分享给大家供大家参考,具体如下:

本文实例讲述了AndroID编程图片加载类ImageLoader定义与用法。分享给大家供大家参考,具体如下:

解析:

1)图片加载使用单例模式,避免多次调用时产生死锁
2)核心对象 LruCache

图片加载时先判断缓存里是否有图片,如果有,就使用缓存里的

没有就加载网络的,然后置入缓存

3)使用了线程池ExecutorService mThreadPool技术
4)使用了Semaphore 信号来控制变量按照先后顺序执行,避免空指针的问题

如何使用:

在Adapter里加载图片时
复制代码 代码如下:ImageLoader.getInstance.loadImage("http://www.baIDu.com/images/kk.jpg",mImageVIEw,true);

源码:

/** * @描述 图片加载类 * @项目名称 App_News * @包名 com.androID.news.tools * @类名 ImageLoader * @author chenlin * @date 2015-3-7 下午7:35:28 * @version 1.0 */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;  private boolean isdiskCacheEnable = true;  private static final String TAG = "ImageLoader";  public enum Type {    FIFO,liFO;  }  private ImageLoader(int threadCount,Type type) {    init(threadCount,type);  }  /**   * 初始化   *   * @param threadCount   * @param type   */  private voID init(int threadCount,Type type) {    initBackThread();    // 获取我们应用的最大可用内存    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(threadCount);    mTaskQueue = new linkedList<Runnable>();    mType = type;    mSemaphoreThreadPool = new Semaphore(threadCount);  }  /**   * 初始化后台轮询线程   */  private voID initBackThread() {    // 后台轮询线程    mPoolThread = new Thread() {      @OverrIDe      public voID run() {        Looper.prepare();        mPoolThreadHandler = new Handler() {          @OverrIDe          public voID handleMessage(Message msg) {            // 线程池去取出一个任务进行执行            mThreadPool.execute(getTask());            try {              mSemaphoreThreadPool.acquire();            } catch (InterruptedException e) {            }          }        };        // 释放一个信号量        mSemaphorePoolThreadHandler.release();        Looper.loop();      };    };    mPoolThread.start();  }  public static ImageLoader getInstance() {    if (mInstance == null) {      synchronized (ImageLoader.class) {        if (mInstance == null) {          mInstance = new ImageLoader(DEAFulT_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;  }  /**   * 根据path为imagevIEw设置图片   *   * @param path   * @param imageVIEw   */  public voID loadImage(final String path,final ImageVIEw imageVIEw,final boolean isFromNet) {    imageVIEw.setTag(path);    if (mUIHandler == null) {      mUIHandler = new Handler() {        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) {      refreashBitmap(path,imageVIEw,bm);    } else {      addTask(buildTask(path,isFromNet));    }  }  /**   * 根据传入的参数,新建一个任务   *   * @param path   * @param imageVIEw   * @param isFromNet   * @return   */  private Runnable buildTask(final String path,final boolean isFromNet) {    return new Runnable() {      @OverrIDe      public voID run() {        Bitmap bm = null;        if (isFromNet) {          file file = getdiskCacheDir(imageVIEw.getContext(),md5(path));          if (file.exists())// 如果在缓存文件中发现          {            Log.e(TAG,"find image :" + path + " in disk cache .");            bm = loadImageFromLocal(file.getabsolutePath(),imageVIEw);          } else {            if (isdiskCacheEnable)// 检测是否开启硬盘缓存            {              boolean downloadState = DownloadimgUtils.downloadimgByUrl(path,file);              if (downloadState)// 如果下载成功              {                Log.e(TAG,"download image :" + path + " to disk cache . path is "                        + file.getabsolutePath());                bm = loadImageFromLocal(file.getabsolutePath(),imageVIEw);              }            } else            // 直接从网络加载            {              Log.e(TAG,"load image :" + path + " to memory.");              bm = DownloadimgUtils.downloadimgByUrl(path,imageVIEw);            }          }        } else {          bm = loadImageFromLocal(path,imageVIEw);        }        // 3、把图片加入到缓存        addBitmapTolruCache(path,bm);        refreashBitmap(path,bm);        mSemaphoreThreadPool.release();      }    };  }  private Bitmap loadImageFromLocal(final String path,final ImageVIEw imageVIEw) {    Bitmap bm;    // 加载图片    // 图片的压缩    // 1、获得图片需要显示的大小    ImageSize imageSize = ImageSizeUtil.getimageVIEwSize(imageVIEw);    // 2、压缩图片    bm = decodeSampledBitmapFromPath(path,imageSize.wIDth,imageSize.height);    return bm;  }  /**   * 从任务队列取出一个方法   *   * @return   */  private Runnable getTask() {    if (mType == Type.FIFO) {      return mTaskQueue.removeFirst();    } else if (mType == Type.liFO) {      return mTaskQueue.removeLast();    }    return null;  }  /**   * 利用签名辅助类,将字符串字节数组   *   * @param str   * @return   */  public String md5(String str) {    byte[] digest = null;    try {      MessageDigest md = MessageDigest.getInstance("md5");      digest = md.digest(str.getBytes());      return bytes2hex02(digest);    } catch (NoSuchAlgorithmException e) {      e.printstacktrace();    }    return null;  }  /**   * 方式二   *   * @param bytes   * @return   */  public String bytes2hex02(byte[] bytes) {    StringBuilder sb = new StringBuilder();    String tmp = null;    for (byte b : bytes) {      // 将每个字节与0xFF进行与运算,然后转化为10进制,然后借助于Integer再转化为16进制      tmp = Integer.toHexString(0xFF & b);      if (tmp.length() == 1)// 每个字节8为,转为16进制标志,2个16进制位      {        tmp = "0" + tmp;      }      sb.append(tmp);    }    return sb.toString();  }  private voID refreashBitmap(final String path,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);  }  /**   * 将图片加入LruCache   *   * @param path   * @param bm   */  protected voID addBitmapTolruCache(String path,Bitmap bm) {    if (getBitmapFromLruCache(path) == null) {      if (bm != null)        mLruCache.put(path,bm);    }  }  /**   * 根据图片需要显示的宽和高对图片进行压缩   *   * @param path   * @param wIDth   * @param height   * @return   */  protected Bitmap decodeSampledBitmapFromPath(String path,int wIDth,int height) {    // 获得图片的宽和高,并不把图片加载到内存中    BitmapFactory.Options options = new BitmapFactory.Options();    options.inJustDecodeBounds = true;    BitmapFactory.decodefile(path,options);    options.inSampleSize = ImageSizeUtil.caculateInSampleSize(options,wIDth,height);    // 使用获得到的InSampleSize再次解析图片    options.inJustDecodeBounds = false;    Bitmap bitmap = BitmapFactory.decodefile(path,options);    return bitmap;  }  private synchronized voID addTask(Runnable runnable) {    mTaskQueue.add(runnable);    // if(mPoolThreadHandler==null)wait();    try {      if (mPoolThreadHandler == null)        mSemaphorePoolThreadHandler.acquire();    } catch (InterruptedException e) {    }    mPoolThreadHandler.sendEmptyMessage(0x110);  }  /**   * 获得缓存图片的地址   *   * @param context   * @param unique@R_403_6889@   * @return   */  public file getdiskCacheDir(Context context,String unique@R_403_6889@) {    String cachePath;    if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {      cachePath = context.getExternalCacheDir().getPath();    } else {      cachePath = context.getCacheDir().getPath();    }    return new file(cachePath + file.separator + unique@R_403_6889@);  }  /**   * 根据path在缓存中获取bitmap   *   * @param key   * @return   */  private Bitmap getBitmapFromLruCache(String key) {    return mLruCache.get(key);  }  private class imgBeanHolder {    Bitmap bitmap;    ImageVIEw imageVIEw;    String path;  }}

相关工具类:

/** * @描述 获取图片大小工具类s * @项目名称 App_News * @包名 com.androID.news.util * @类名 ImageSizeUtil * @author chenlin * @date 2014-3-7 下午7:37:50 * @version 1.0 */public class ImageSizeUtil {  /**   * 根据需求的宽和高以及图片实际的宽和高计算SampleSize   *   * @param options   * @param wIDth   * @param height   * @return   */  public static int caculateInSampleSize(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获适当的压缩的宽和高   *   * @param imageVIEw   * @return   */  public static ImageSize getimageVIEwSize(ImageVIEw imageVIEw) {    ImageSize imageSize = new ImageSize();    displayMetrics displayMetrics = imageVIEw.getContext().getResources().getdisplayMetrics();    LayoutParams lp = imageVIEw.getLayoutParams();    int wIDth = imageVIEw.getWIDth();// 获取imagevIEw的实际宽度    if (lp != null) {      if (wIDth <= 0) {        wIDth = lp.wIDth;// 获取imagevIEw在layout中声明的宽度      }    }    if (wIDth <= 0) {      // wIDth = imageVIEw.getMaxWIDth();// 检查最大值      wIDth = getimageVIEwFIEldValue(imageVIEw,"mMaxWIDth");    }    if (wIDth <= 0) {      wIDth = displayMetrics.wIDthPixels;    }    int height = imageVIEw.getHeight();// 获取imagevIEw的实际高度    if (lp != null) {      if (height <= 0) {        height = lp.height;// 获取imagevIEw在layout中声明的宽度      }    }    if (height <= 0) {      height = getimageVIEwFIEldValue(imageVIEw,"mMaxHeight");// 检查最大值    }    if (height <= 0) {      height = displayMetrics.heightPixels;    }    imageSize.wIDth = wIDth;    imageSize.height = height;    return imageSize;  }  public static class ImageSize {    public int wIDth;    public int height;  }  /**   * 通过反射获取imagevIEw的某个属性值   *   * @param object   * @param fIEld@R_403_6889@   * @return   */  private static int getimageVIEwFIEldValue(Object object,String fIEld@R_403_6889@) {    int value = 0;    try {      FIEld fIEld = ImageVIEw.class.getDeclaredFIEld(fIEld@R_403_6889@);      fIEld.setAccessible(true);      int fIEldValue = fIEld.getInt(object);      if (fIEldValue > 0 && fIEldValue < Integer.MAX_VALUE) {        value = fIEldValue;      }    } catch (Exception e) {    }    return value;  }}

更多关于AndroID相关内容感兴趣的读者可查看本站专题:《Android图形与图像处理技巧总结》、《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》

希望本文所述对大家AndroID程序设计有所帮助。

总结

以上是内存溢出为你收集整理的Android编程图片加载类ImageLoader定义与用法实例分析全部内容,希望文章能够帮你解决Android编程图片加载类ImageLoader定义与用法实例分析所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1143420.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-31
下一篇2022-05-31

发表评论

登录后才能评论

评论列表(0条)

    保存