Universal-Image-Loader 图片异步加载并缓存

Android 开发关于图片的管理的程序相对比较麻烦,需要考虑线程,缓存,内存溢出等一系列的问题。经过多方查找终于找到一个不错的开源组件(Universal-Image-Loader),这个组件也是异步加载并缓存的常用组件之一,通过反编译可以在很多应用上都能看到他的身影。

GitHub 上的下载网址是:https://github.com/nostra13/Android-Universal-Image-Loader ,下载最新的库文件,并且导入到项目的 LIB 下便可以使用。

一、介绍


Android-Universal-Image-Loader 是一个开源的 UI 组件程序,该项目的目的是提供一个可重复使用的仪器为异步图像加载,缓存和显示。他已经封装好了一些类和方法,我们可以直接拿来使用,而不用花费自己大量的精力去出来线程,缓存,内存溢出等问题。

二:特点


  1. 多线程下载图片,图片可以来源于网络,文件系统,项目文件夹 assets 中以及 drawable 中等。

  2. 支持随意的配置 ImageLoader,例如线程池,图片下载器,内存缓存策略,硬盘缓存策略,图片显示选项以及其他的一些配置。

  3. 支持图片的内存缓存,文件系统缓存或者 SD 卡缓存。

  4. 支持图片下载过程的监听。

  5. 根据控件(ImageView)的大小对 Bitmap 进行裁剪,减少 Bitmap 占用过多的内存。

  6. 较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片,一般使用在 ListView,GridView 中,滑动过程中暂停加载图片,停止滑动的时候去加载图片。

  7. 提供在较慢的网络下对图片进行加载。

流程图:

Universal-Image-Loader 流程图

三、使用方法


1、导入jar文件

2、添加网络权限

  1. <uses-permission android:name="android.permission.INTERNET" />
  2. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

3、配置 ImageLoaderConfiguration 这个类实现全局 ImageLoader 的实现情况。可以选择在 Application 中初始化设置该类。

  1. ImageLoaderConfiguration config = new ImageLoaderConfiguration
  2. .Builder(context)
  3. .memoryCacheExtraOptions(480, 800) // max width, max height,即保存的每个缓存文件的最大长宽
  4. .discCacheExtraOptions(480, 800, CompressFormat.JPEG, 75, null) // Can slow ImageLoader, use it carefully (Better don't use it)/设置缓存的详细信息,最好不要设置这个
  5. .threadPoolSize(3) // 线程池内加载的数量
  6. .threadPriority(Thread.NORM_PRIORITY - 2)
  7. .denyCacheImageMultipleSizesInMemory()
  8. .memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024)) // You can pass your own memory cache implementation/你可以通过自己的内存缓存实现
  9. .memoryCacheSize(2 * 1024 * 1024)
  10. .discCacheSize(50 * 1024 * 1024)
  11. .discCacheFileNameGenerator(new Md5FileNameGenerator()) // 将保存的时候的URI名称用MD5 加密
  12. .tasksProcessingOrder(QueueProcessingType.LIFO)
  13. .discCacheFileCount(100) // 缓存的文件数量
  14. .discCache(new UnlimitedDiscCache(cacheDir)) // 自定义缓存路径
  15. .defaultDisplayImageOptions(DisplayImageOptions.createSimple())
  16. .imageDownloader(new BaseImageDownloader(context, 5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)超时时间
  17. .writeDebugLogs() // Remove for release app
  18. .build(); // 开始构建

以上配置依个人需要进行选择配置,配置好之后调用下面方法进行初始化:

  1. ImageLoader.getInstance().init(config); // 全局初始化此配置

注:ImageLoaderConfiguration 配置中的.discCacheFileNameGenerator()方法是将缓存下来的文件以什么方式命名,里面可以调用的方法有 :

  1. new Md5FileNameGenerator() // 使用 MD5 对 UIL 进行加密命名
  2. new HashCodeFileNameGenerator() // 使用 HASHCODE 对 UIL 进行加密命名

4、使用 ImageLoader 进行图片加载的时候,先要实例化 ImageLoader,调用以下方法进行实例化,在每个布局里面都要实例化后再使用。

  1. protected ImageLoader imageLoader = ImageLoader.getInstance();

5、对需要显示图片的各种格式 DisplayImageOptions 的设置:

  1. DisplayImageOptions options;
  2. options = new DisplayImageOptions.Builder()
  3. .showImageOnLoading(R.drawable.ic_launcher) // 设置图片在下载期间显示的图片
  4. .showImageForEmptyUri(R.drawable.ic_launcher) // 设置图片 Uri 为空或是错误的时候显示的图片
  5. .showImageOnFail(R.drawable.ic_launcher) // 设置图片加载/解码过程中错误时候显示的图片
  6. .cacheInMemory(true) // 设置下载的图片是否缓存在内存中
  7. .cacheOnDisc(true) // 设置下载的图片是否缓存在 SD 卡中
  8. .considerExifParams(true) // 是否考虑 JPEG 图像 EXIF 参数(旋转,翻转)
  9. .imageScaleType(ImageScaleType.EXACTLY_STRETCHED) // 设置图片以如何的编码方式显示
  10. .bitmapConfig(Bitmap.Config.RGB_565) // 设置图片的解码类型
  11. .decodingOptions(android.graphics.BitmapFactory.Options decodingOptions) // 设置图片的解码配置
  12. //.delayBeforeLoading(int delayInMillis) // int delayInMillis为你设置的下载前的延迟时间
  13. // 设置图片加入缓存前,对 bitmap 进行设置
  14. //.preProcessor(BitmapProcessor preProcessor)
  15. .resetViewBeforeLoading(true) // 设置图片在下载前是否重置,复位
  16. .displayer(new RoundedBitmapDisplayer(20)) // 是否设置为圆角,弧度为多少
  17. .displayer(new FadeInBitmapDisplayer(100)) // 是否图片加载好后渐入的动画时间
  18. .build(); // 构建完成

以上配置依个人需要进行选择配置,不需要的可以不配置。

注:以上配置中的.imageScaleType(ImageScaleType imageScaleType)是设置图片的缩放方式,缩放类型 mageScaleType 有:

  1. ImageScaleType.EXACTLY // 图像将完全按比例缩小的目标大小
  2. ImageScaleType.EXACTLY_STRETCHED // 图片会缩放到目标大小完全
  3. ImageScaleType.IN_SAMPLE_INT // 图像将被二次采样的整数倍
  4. ImageScaleType.IN_SAMPLE_POWER_OF_2 // 图片将降低2倍,直到下一减少步骤,使图像更小的目标大小
  5. ImageScaleType.NONE // 图片不会调整

.displayer(BitmapDisplayer displayer)是设置图片的显示方式,显示方式 displayer:

  1. RoundedBitmapDisplayer(int roundPixels) // 设置圆角图片
  2. FakeBitmapDisplayer() // 这个类什么都没做
  3. FadeInBitmapDisplayer(int durationMillis) // 设置图片渐显的时间
  4. SimpleBitmapDisplayer() // 正常显示一张图片

现在开始按照需求使用缓存

1、纯粹为了加载默认配置的一个图片的方法

  1. /**
  2. * @param url 图片的 URL 地址
  3. * @param imageView 承载图片的 IMAGEVIEW 控件
  4. */
  5. public void displayImage(String url, ImageView imageView) {}
  1. // 具体实现
  2. ImageLoader.getInstance().displayImage(imageUrl, imageView);

2、加载自定义配置的一个图片的方法

  1. /**
  2. * @param url 图片的 URL 地址
  3. * @param imageView 承载图片的 IMAGEVIEW 控件
  4. * @param options DisplayImageOptions 配置文件
  5. */
  6. public void displayImage(String url, ImageView imageView, DisplayImageOptions options) {}
  1. // 具体实现
  2. ImageLoader.getInstance().displayImage(imageUrl, imageView, options);

3、图片加载时候带加载情况的监听方法

  1. /**
  2. * @param url 图片的 URL 地址
  3. * @param imageView 承载图片的 IMAGEVIEW 控件
  4. * @param options DisplayImageOptions 配置文件
  5. * @param listener 用于监听图片的下载情况。
  6. */
  7. public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,ImageLoadingListener listener) {}
  1. // 具体实现
  2. imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {
  3. @Override
  4. public void onLoadingStarted() {
  5. // 开始加载的时候执行
  6. }
  7. @Override
  8. public void onLoadingFailed(FailReason failReason) {
  9. // 加载失败的时候执行
  10. }
  11. @Override
  12. public void onLoadingComplete(Bitmap loadedImage) {
  13. // 加载成功的时候执行
  14. }
  15. @Override
  16. public void onLoadingCancelled() {
  17. // 加载取消的时候执行
  18. }
  19. });

4、图片加载时候,带监听又带加载进度条的情况

  1. public void loadImage(String uri, ImageSize targetImageSize, DisplayImageOptions options, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {}
  1. // 具体实现
  2. imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {
  3. @Override
  4. public void onLoadingStarted() {
  5. // 开始加载的时候执行
  6. }
  7. @Override
  8. public void onLoadingFailed(FailReason failReason) {
  9. // 加载失败的时候执行
  10. }
  11. @Override
  12. public void onLoadingComplete(Bitmap loadedImage) {
  13. // 加载成功的时候执行
  14. }
  15. @Override
  16. public void onLoadingCancelled() {
  17. // 加载取消的时候执行
  18. }, new ImageLoadingProgressListener() {
  19. @Override
  20. public void onProgressUpdate(String imageUri, View view, int current, int total) {
  21. // 在这里更新 ProgressBar 的进度信息
  22. }
  23. });

四、注意事项


  1. 上述提到的 2 个权限必须加入,否则会出错。

  2. ImageLoaderConfiguration 必须配置并且全局化的初始化这个配置ImageLoader.getInstance().init(config);否则也会出现错误提示。

  3. ImageLoader 是根据 ImageView 的 height,width 确定图片的宽高。

  4. 如果经常出现 OOM

    • 减少配置之中线程池的大小,.threadPoolSize()推荐1-5;

    • 使用.bitmapConfig(Bitmap.config.RGB_565)代替 ARGB_8888;

    • 使用.imageScaleType(ImageScaleType.IN_SAMPLE_INT)或者try.imageScaleType(ImageScaleType.EXACTLY);

    • 避免使用 RoundedBitmapDisplayer 他会创建新的 ARGB_8888 格式的 Bitmap 对象;

    • 使用.memoryCache(new WeakMemoryCache()),不要使用.cacheInMemory();

(完)