栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

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

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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);

源码:


public class ImageLoader {
  private static ImageLoader mInstance;
  
  private LruCache mLruCache;
  
  private ExecutorService mThreadPool;
  private static final int DEAFULT_THREAD_COUNT = 1;
  
  private Type mType = Type.LIFO;
  
  private linkedList mTaskQueue;
  
  private Thread mPoolThread;
  private Handler mPoolThreadHandler;
  
  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);
  }
  
  private void init(int threadCount, Type type) {
    initBackThread();
    // 获取我们应用的最大可用内存
    int maxMemory = (int) Runtime.getRuntime().maxMemory();
    int cacheMemory = maxMemory / 8;
    mLruCache = new LruCache(cacheMemory) {
      @Override
      protected int sizeOf(String key, Bitmap value) {
 return value.getRowBytes() * value.getHeight();
      }
    };
    // 创建线程池
    mThreadPool = Executors.newFixedThreadPool(threadCount);
    mTaskQueue = new linkedList();
    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;
  }
  
  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, imageView, isFromNet));
    }
  }
  
  private Runnable buildTask(final String path, final ImageView imageView, 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, imageView, 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;
  }
  
  private Runnable getTask() {
    if (mType == Type.FIFO) {
      return mTaskQueue.removeFirst();
    } else if (mType == Type.LIFO) {
      return mTaskQueue.removeLast();
    }
    return null;
  }
  
  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;
  }
  
  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, final 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 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);
  }
  
  public File getDiskCacheDir(Context context, String uniqueName) {
    String cachePath;
    if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
      cachePath = context.getExternalCacheDir().getPath();
    } else {
      cachePath = context.getCacheDir().getPath();
    }
    return new File(cachePath + File.separator + uniqueName);
  }
  
  private Bitmap getBitmapFromLruCache(String key) {
    return mLruCache.get(key);
  }
  private class ImgBeanHolder {
    Bitmap bitmap;
    ImageView imageView;
    String path;
  }
}

相关工具类:


public class ImageSizeUtil {
  
  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;
  }
  
  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;
  }
  
  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) {
    }
    return value;
  }
}

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

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/157016.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号