Android开发中,多少会接触到异步加载图片,或者加载大量图片的问题,而加载图片我们常常会遇到许多的问题,比如说图片的错乱,OOM等问题,对于这些问题解决起来会比较吃力,比较著名的就是Universal-Image-Loader,该项目可以在于Github搜索到.


特征:

  1. 多线程下载图片,图片可以来源于网络,文件系统,项目文件夹assets中以及drawable中等
  2. 支持随意的配置ImageLoader,例如线程池,图片下载器,内存缓存策略,硬盘缓存策略,图片显示选项以及其他的一些配置
  3. 支持图片的内存缓存,文件系统缓存或者SD卡缓存
  4. 支持图片下载过程的监听
  5. 根据控件(ImageView)的大小对Bitmap进行裁剪,减少Bitmap占用过多的内存
  6. 较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片,一般使用在ListView,GridView中,滑动过程中暂停加载图片,停止滑动的时候去加载图片
  7. 提供在较慢的网络下对图片进行加载

使用:

第一步:添加依赖到项目中,或者将jar包添加中libs项目下

compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'

第二步:添加权限

    <uses-permission android:name="android.permission.INTERNET" />
<!-- Include following permission if you want to cache images on SD card -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

第三步:在Application或者Activity中初始化

public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate(); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)
.threadPoolSize(5)//线程池数量
.memoryCacheSize(2 * 1024 * 1024)//设置内存缓存大小2M
.diskCacheSize(50 * 1024 * 1024)//磁盘缓存50M
.diskCacheFileCount(100)//缓存文件最大数量
.diskCacheFileNameGenerator(new Md5FileNameGenerator())//缓存文件的命名策略, 以md5(url)命名
.build(); ImageLoader.getInstance().init(config);
}
}

第四步:在AndroidManifest.xml配置

<application
android:name=".MyApplication"
> </application>

第五步:加载图片

方法一:LoaderImage加载

final ImageView mImageView = (ImageView) findViewById(R.id.image);
String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg";
ImageLoader.getInstance().loadImage(imageUrl, new SimpleImageLoadingListener(){
@Override
public void onLoadingComplete(String imageUri, View view,Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
mImageView.setImageBitmap(loadedImage);
} });
final ImageView mImageView = (ImageView) findViewById(R.id.image);
String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg"; ImageLoader.getInstance().loadImage(imageUrl, new ImageLoadingListener() { @Override
public void onLoadingStarted(String imageUri, View view) { } @Override
public void onLoadingFailed(String imageUri, View view,
FailReason failReason) { } @Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
mImageView.setImageBitmap(loadedImage);
} @Override
public void onLoadingCancelled(String imageUri, View view) { }
});

传入图片的url和ImageLoaderListener, 在回调方法onLoadingComplete()中将loadedImage设置到ImageView上面就行了,如果你觉得传入ImageLoaderListener太复杂了,我们可以使用SimpleImageLoadingListener类,该类提供了ImageLoaderListener接口方法的空实现,使用的是缺省适配器模式

如果我们要指定图片的大小该怎么办呢,这也好办,初始化一个ImageSize对象,指定图片的宽和高,代码如下

final ImageView mImageView = (ImageView) findViewById(R.id.image);
String imageUrl = "https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg"; ImageSize mImageSize = new ImageSize(100, 100); ImageLoader.getInstance().loadImage(imageUrl, mImageSize, new SimpleImageLoadingListener(){ @Override
public void onLoadingComplete(String imageUri, View view,
Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
mImageView.setImageBitmap(loadedImage);
} });

上面只是很简单的使用ImageLoader来加载网络图片,在实际的开发中,我们并不会这么使用,那我们平常会怎么使用呢?我们会用到DisplayImageOptions,他可以配置一些图片显示的选项,比如图片在加载中ImageView显示的图片,是否需要使用内存缓存,是否需要使用文件缓存等等,可供我们选择的配置如下

方法二:DisplayImageOptions加载图片

ivImage = (ImageView) findViewById(R.id.iv_image);
String url = "http://d.hiphotos.baidu" +
".com/image/pic/item/5882b2b7d0a20cf482c772bf73094b36acaf997f.jpg";
//展示图片选项
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.mipmap.ic_launcher)//加载中图片
.showImageOnFail(R.mipmap.error)//失败图片
.showImageForEmptyUri(R.mipmap.error)//内容为空的图片
.cacheInMemory(true) // default 开启内存缓存
.cacheOnDisk(true) // default 开启磁盘缓存
.bitmapConfig(Bitmap.Config.ARGB_8888)//图片格式
//.displayer(new FadeInBitmapDisplayer(1000))//图片展示方式, 透明度渐显的淡入
//.displayer(new CircleBitmapDisplayer(Color.TRANSPARENT))//圆形图片, 必须设置图片宽高
//.displayer(new RoundedBitmapDisplayer(10))//圆角矩形
.displayer(new RoundedVignetteBitmapDisplayer(10, 10))
.build(); ImageLoader.getInstance().displayImage(url, ivImage, options);

从上面的代码中,我们可以看出,使用displayImage()比使用loadImage()方便很多,也不需要添加ImageLoadingListener接口,我们也不需要手动设置ImageView显示Bitmap对象,直接将ImageView作为参数传递到displayImage()中就行了,图片显示的配置选项中,我们添加了一个图片加载中ImageVIew上面显示的图片,以及图片加载出现错误显示的图片

我们在加载网络图片的时候,经常有需要显示图片下载进度的需求,Universal-Image-Loader当然也提供这样的功能,只需要在displayImage()方法中传入ImageLoadingProgressListener接口就行了,代码如下

imageLoader.displayImage(imageUrl, mImageView, options, new SimpleImageLoadingListener(), new ImageLoadingProgressListener() {

    @Override
public void onProgressUpdate(String imageUri, View view, int current,int total) { }
});

由于displayImage()方法中带ImageLoadingProgressListener参数的方法都有带ImageLoadingListener参数,所以我这里直接new 一个SimpleImageLoadingListener,然后我们就可以在回调方法onProgressUpdate()得到图片的加载进度。

使用Universal-Image-Loader框架不仅可以加载网络图片,还可以加载sd卡中的图片,Content provider等,使用也很简单,只是将图片的url稍加的改变下就行了

相信大部分人都是使用GridView,ListView来显示大量的图片,而当我们快速滑动GridView,ListView,我们希望能停止图片的加载,而在GridView,ListView停止滑动的时候加载当前界面的图片,这个框架当然也提供这个功能,使用起来也很简单,它提供了PauseOnScrollListener这个类来控制ListView,GridView滑动过程中停止去加载图片,该类使用的是代理模式

listView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling));

gridView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling));

第一个参数就是我们的图片加载对象ImageLoader, 第二个是控制是否在滑动过程中暂停加载图片,如果需要暂停传true就行了,第三个参数控制猛的滑动界面的时候图片是否加载


详细配置

// ImageLoaderConfiguration 详细配置
File cacheDir = StorageUtils.getOwnCacheDirectory(getApplicationContext(), "imageloader/Cache"); // 自定义缓存文件夹
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.memoryCacheExtraOptions(480, 800) // 指定缓存到内存时图片的大小,默认是屏幕尺寸的长宽
.diskCacheExtraOptions(480, 800, null) // 指定缓存到硬盘时图片的大小,并不建议使用
.taskExecutor(new Executor()) // 自定义一个线程来加载和显示图片
.taskExecutorForCachedImages(new Executor())// 自定义一个线程来缓存图片
.threadPoolSize(3) // default, 指定线程池大小
.threadPriority(Thread.NORM_PRIORITY - 2) // default ,指定线程优先级
.tasksProcessingOrder(QueueProcessingType.FIFO) // default , 指定加载显示图片的任务队列的类型
.denyCacheImageMultipleSizesInMemory() // 禁止在内存中缓存同一张图片的多个尺寸类型
.memoryCache(new LruMemoryCache(2 * 1024 * 1024)) // 指定内存缓存的大小,默认值为1/8 应用的最大可用内存
.memoryCacheSize(2 * 1024 * 1024)
.memoryCacheSizePercentage(13) // default
.diskCache(new UnlimitedDiskCache(cacheDir)) // default , 指定硬盘缓存的地址
.diskCacheSize(50 * 1024 * 1024) // 指定硬盘缓存的大小
.diskCacheFileCount(100) // 指定硬盘缓存的文件个数
.diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default , 指定硬盘缓存时文件名的生成器
.imageDownloader(new BaseImageDownloader(context)) // default , 指定图片下载器
.imageDecoder(new BaseImageDecoder()) // default , 指定图片解码器
.defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default , 指定图片显示的配置
.writeDebugLogs() // 是否显示Log
.build(); // ImageLoaderConfiguration 简单初始化
ImageLoaderConfiguration configuration = ImageLoaderConfiguration.createDefault(this);
// 初始化配置
ImageLoader.getInstance().init(configuration);

DisplayImageOptions 参数详解

    DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub) // 图片正在加载时显示的图片资源ID
.showImageForEmptyUri(R.drawable.ic_empty) // URI为空时显示的图片资源ID
.showImageOnFail(R.drawable.ic_error) // 图片加载失败时显示的图片资源ID
.resetViewBeforeLoading(false) // default 图片在下载前是否重置,复位
.delayBeforeLoading(1000) // 图片开始加载前的延时.默认是0
.cacheInMemory(false) // default , 是否缓存在内存中, 默认不缓存
.cacheOnDisk(false) // default , 是否缓存在硬盘 , 默认不缓存
.preProcessor(new BitmapProcessor) // 设置图片缓存在内存前的图片处理器
.postProcessor(new BitmapProcessor) // 设置图片在缓存到内存以后 , 显示在界面之前的图片处理器
.extraForDownloader(...) // 为图片下载设置辅助参数
.considerExifParams(false) // default , 设置是否考虑JPEG图片的EXIF参数信息,默认不考虑
.imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default , 指定图片缩放的方式,ListView/GridView/Gallery推荐使用此默认值
.bitmapConfig(Bitmap.Config.ARGB_8888) // default , 指定图片的质量,默认是 ARGB_8888
.decodingOptions(...) // 指定图片的解码方式
.displayer(new SimpleBitmapDisplayer()) // default , 设置图片显示的方式,用于自定义
.handler(new Handler()) // default ,设置图片显示的方式和ImageLoadingListener的监听, 用于自定义
.build();

OOM

虽然这个框架有很好的缓存机制,有效的避免了OOM的产生,一般的情况下产生OOM的概率比较小,但是并不能保证OutOfMemoryError永远不发生,这个框架对于OutOfMemoryError做了简单的catch,保证我们的程序遇到OOM而不被crash掉,但是如果我们使用该框架经常发生OOM,我们应该怎么去改善呢?

  • 减少线程池中线程的个数,在ImageLoaderConfiguration中的(.threadPoolSize)中配置,推荐配置1-5
  • 在DisplayImageOptions选项中配置bitmapConfig为Bitmap.Config.RGB_565,因为默认是ARGB_8888, 使用RGB_565会比使用ARGB_8888少消耗2倍的内存
  • 在ImageLoaderConfiguration中配置图片的内存缓存为memoryCache(new WeakMemoryCache()) 或者不使用内存缓存
  • 在DisplayImageOptions选项中设置.imageScaleType(ImageScaleType.IN_SAMPLE_INT)或者imageScaleType(ImageScaleType.EXACTLY)

通过上面这些,相信大家对Universal-Image-Loader框架的使用已经非常的了解了,我们在使用该框架的时候尽量的使用displayImage()方法去加载图片,loadImage()是将图片对象回调到ImageLoadingListener接口的onLoadingComplete()方法中,需要我们手动去设置到ImageView上面,displayImage()方法中,对ImageView对象使用的是Weak references,方便垃圾回收器回收ImageView对象,如果我们要加载固定大小的图片的时候,使用loadImage()方法需要传递一个ImageSize对象,而displayImage()方法会根据ImageView对象的测量值,或者android:layout_width and android:layout_height设定的值,或者android:maxWidth and/or android:maxHeight设定的值来裁剪图片


Normal
0

7.8 磅
0
2

false
false
false

EN-US
ZH-CN
X-NONE

MicrosoftInternetExplorer4

/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.5pt;
mso-bidi-font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;
mso-font-kerning:1.0pt;}

最新文章

  1. html5移动web开发笔记(一)Web 存储
  2. JavaScript中清空数组的三种方式
  3. C++IO关于cin&gt;&gt;和getline的理解
  4. 三国杀3v3心法——总述篇
  5. linux网络命令
  6. centos Flash Player插件的安装
  7. 使用eclipse开发
  8. dev 激活没有权限问题
  9. RAD DELPHI XE5的android开发环境配置
  10. Ubuntu之网络配置
  11. 介绍一个成功的 Git 分支模型 Release 分支
  12. UVA 322 ships (POJ 1138)
  13. 开发中少不了的Fun -- 获取地址栏URL参数
  14. Python模块 2
  15. SharePoint 2013 新特性 (三) 破改式 &mdash;&mdash; 设计管理器的使用 [2.HTML变身模板页]
  16. B树与B+ 树
  17. ES5-ES6-ES7_解构赋值
  18. android动态设置组件LayoutParams
  19. win2003 序列号 windows2003 sp2可用序列号大全(准版与企业版)
  20. 高级数据类型-- 字符串(str),切片

热门文章

  1. 关于C++跨平台
  2. zencart新增分类点击不进去的解决办法
  3. 解决Windows jmeter Non HTTP response message: Address already in use: connect 错误(转载)
  4. mysql中给查询结果添加序号列
  5. 一步一步带你安装史上最难安装的 vim 插件
  6. tomcat启动失败_严重: A child container failed during start
  7. Gradle 配置国内镜像
  8. Kafka、RabbitMQ、RocketMQ等消息中间件的介绍和对比(转)
  9. sysbench简易使用
  10. pro git 读书笔记 3 Git 分支