Universal-Image-Loader的使用,缓存图片,防止错位,滑动暂停下载
该框架的特点:
1.可以对缓存的大小进行设置,磁盘缓存的路径已经大小,文件夹名的设置
2.很方便的控制滑动屏幕的时候,停止图片的下载
1.添加依赖与权限:
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
<!-- 添加网络权限,如果需要从网络上下载图片 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 添加写外部存储权限,如果需要往sd卡上写图片的话 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2.在Application或者activity中进行配置,来确保在Application初始化的时候,整个App中有一个ImageLoader存在
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); 很多都是默认的设置,并且在实际使用中不需要全部都进行设置,根据需要设置部分就行了 ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this) //即保存的每个缓存文件的最大长宽,默认等于你的屏幕尺寸,设备屏幕宽高 .memoryCacheExtraOptions(480, 800) .threadPoolSize(3)//线程池内加载的数量 .threadPriority(Thread.NORM_PRIORITY - 2)//线程优先级,普通-2 //设置内存缓存不允许缓存一张图片的多个尺寸,默认允许。 .denyCacheImageMultipleSizesInMemory() .memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024)) //你可以通过自己的内存缓存实现 //memoryCacheSize 为 0,则设置该内存缓存的最大字节数为 App 最大可用内存的 1/8。 // 创建最大的内存缓存百分比,默认为 13% .memoryCacheSizePercentage(13) .memoryCacheSize(2 * 1024 * 1024) //内存缓存大小 .diskCacheSize(50 * 1024 * 1024) //磁盘缓存大小 // 硬盘缓存文件名生成器,默认为哈希文件名生成器 new HashCodeFileNameGenerator() .diskCacheFileNameGenerator(new Md5FileNameGenerator())//将保存的时候的URI名称用MD5 加密 //集合类型的队列处理任务加载和显示图像,LIFO为后进先出,默认为:FIFO 先进先出 .tasksProcessingOrder(QueueProcessingType.LIFO) .diskCacheFileCount(100) //缓存的文件数量 .diskCache(new UnlimitedDiskCache(new File(Environment.getExternalStorageDirectory()+"/文件名")))//自定义缓存路径 .imageDownloader(new BaseImageDownloader(this, 5 * 1000, 30 * 1000)) //网络连接时间 (5 s), readTimeout(30 s)超时时间 //图片显示的配置项。比如加载前、加载中、加载失败应该显示的占位图片,图片是否需要在磁盘缓存,是否需要在内存缓存等。 .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) .writeDebugLogs() // 显示调试的log信息 .build();//开始构建 ImageLoader.getInstance().init(config); } }
具体参数说明:
/** 内存缓存与磁盘缓存的设置: config.diskCache(new )可以使用的对象如下: FileCountLimitedDiscCache(可以设定缓存图片的个数,当超过设定值,删除掉最先加入到硬盘的文件) LimitedAgeDiscCache(设定文件存活的最长时间,当超过这个值,就删除该文件) TotalSizeLimitedDiscCache(设定缓存bitmap的最大值,当超过这个值,删除最先加入到硬盘的文件) UnlimitedDiscCache(这个缓存类没有任何的限制) config.memoryCache(new UsingFreqLimitedMemoryCache())可以使用的缓存: 1. 只使用的是强引用缓存 LruMemoryCache(这个类就是这个开源框架默认的内存缓存类,缓存的是bitmap的强引用,下面我会从源码上面分析这个类) 2.使用强引用和弱引用相结合的缓存有 UsingFreqLimitedMemoryCache(如果缓存的图片总量超过限定值,先删除使用频率最小的bitmap) LRULimitedMemoryCache(这个也是使用的lru算法,和LruMemoryCache不同的是,他缓存的是bitmap的弱引用) FIFOLimitedMemoryCache(先进先出的缓存策略,当超过设定值,先删除最先加入缓存的bitmap) LargestLimitedMemoryCache(当超过缓存限定值,先删除最大的bitmap对象) LimitedAgeMemoryCache(当 bitmap加入缓存中的时间超过我们设定的值,将其删除) 3.只使用弱引用缓存 WeakMemoryCache(这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收掉) */
基本的设置,也是推荐的初始化:
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(this); config.threadPriority(Thread.NORM_PRIORITY - 2);//普通优先级-2 config.denyCacheImageMultipleSizesInMemory();//设置内存缓存不允许缓存一张图片的多个尺寸 config.diskCacheFileNameGenerator(new Md5FileNameGenerator());//MD5命名文件 config.diskCacheSize(50 * 1024 * 1024); // 50 M磁盘缓存 config.tasksProcessingOrder(QueueProcessingType.LIFO);//后进先出 config.diskCache(new UnlimitedDiskCache(new File(Environment.getExternalStorageDirectory()+"/缓存的文件夹名"))); if (BuildConfig.DEBUG){ config.writeDebugLogs();//发布release包时,移除log信息 } ImageLoader.getInstance().init(config.build()); } }
3.初始化后就可以使用ImageLoader进行图片的下载了:
如果没有给ImageLoader.displayImage(xxx)这个方法传递Display Options,那么这个方法将会使用默认的Display Options
DisplayImageOptions options = new DisplayImageOptions.Builder() 默认的参数配置 // 正在加载时显示的占位图 .showImageOnLoading(R.drawable.ic_stub) // URL为空时显示的占位图 .showImageForEmptyUri(R.drawable.ic_empty) // 加载失败时显示的占位图 .showImageOnFail(R.drawable.ic_error) // 在加载前是否重置 view,默认为false .resetViewBeforeLoading(false) //设置在开始加载前的延迟时间,单位为毫秒,通过 Builder 构建的对象默认为 0 .delayBeforeLoading(1000) // 是否缓存在内存中,通过 Builder 构建的对象默认为 false .cacheInMemory(false) // 是否缓存在磁盘中,通过 Builder 构建的对象默认为 false。 .cacheOnDisk(false) //缓存在内存之前的处理程序,默认为 null .preProcessor(null) //缓存在内存之后的处理程序,默认为 null。 .postProcessor(null) //下载器需要的辅助信息。下载时传入ImageDownloader.getStream(String, Object)的对象,方便用户自己扩展,默认为 null。 .extraForDownloader(null) // 是否考虑图片的 EXIF 信息,通过 Builder 构建的对象默认为 false。 .considerExifParams(false) // 图片的缩放类型,通过 Builder 构建的对象默认为IN_SAMPLE_POWER_OF_2 .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // bitmap的质量,默认为ARGB_8888 .bitmapConfig(Bitmap.Config.ARGB_8888) //为 BitmapFactory.Options,用于BitmapFactory.decodeStream(imageStream, null, decodingOptions)得到图片尺寸等信息。 .decodingOptions(null) // 在ImageAware中显示 bitmap 对象的接口。可在实现中对 bitmap 做一些额外处理,比如加圆角、动画效果。 .displayer(new SimpleBitmapDisplayer()) // handler 对象,默认为 null .handler(new Handler()) .build();
4.加载网络图片的方式
//1.火球加载图片的对象,单例 ImageLoader imageLoader = ImageLoader.getInstance(); //2.为图片设置参数 DisplayImageOptions options = new DisplayImageOptions.Builder() .showImageOnLoading(R.mipmap.ic_launcher) //设置图片在下载期间显示的图片 .showImageForEmptyUri(R.mipmap.ic_launcher)//设置图片Uri为空或是错误的时候显示的图片 .showImageOnFail(R.mipmap.ic_launcher) //设置图片加载/解码过程中错误时候显示的图片 .cacheInMemory(true)//设置下载的图片是否缓存在内存中 .cacheOnDisk(true)//设置下载的图片是否缓存在SD卡中 .considerExifParams(true) //是否考虑JPEG图像EXIF参数(旋转,翻转) /* EXACTLY :图像将完全按比例缩小的目标大小 EXACTLY_STRETCHED:图片会缩放到目标大小完全 IN_SAMPLE_INT:图像将被二次采样的整数倍 IN_SAMPLE_POWER_OF_2:图片将降低2倍,直到下一减少步骤,使图像更小的目标大小 NONE:图片不会调整 */ .imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//设置图片以如何的编码方式显示 .bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型 //.delayBeforeLoading(int delayInMillis)//delayInMillis为你设置的下载前的延迟时间 //设置图片加入缓存前,对bitmap进行设置 //.preProcessor(BitmapProcessor preProcessor) .resetViewBeforeLoading(true)//设置图片在下载前是否重置,复位 /* 显示方式displayer:效果不能重叠 RoundedBitmapDisplayer(int roundPixels)设置图片四个角的弧度,
new CircleBitmapDisplayer() 就能显示圆形图 FakeBitmapDisplayer()这个类什么都没做 FadeInBitmapDisplayer(int durationMillis)设置图片渐显的时间 SimpleBitmapDisplayer()正常显示一张图片 */ .displayer(new RoundedBitmapDisplayer(20))//是否设置为圆角,弧度为多少 .displayer(new FadeInBitmapDisplayer(100))//是否图片加载好后渐入的动画时间 .build();//构建完成 //3.加载默认配置的一个图片 ImageLoader.getInstance().displayImage(imageUrl, imageView) // 加载自定义配置的一个图片的 ImageLoader.getInstance().displayImage(imageUrl, imageView,options);//options代表上面设置的参数 //图片加载时候带加载情况的监听 imageLoader.displayImage(imageUrl, imageView, options, 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) { //加载成功的时候执行 } @Override public void onLoadingCancelled(String imageUri, View view) { //加载取消的时候执行 } }); //图片加载时候,带监听又带加载进度条的情况 imageLoader.displayImage(imageUrl, imageView, options, 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) { //加载成功的时候执行,view为imageView,在这里判断tag防止错位 } @Override public void onLoadingCancelled(String imageUri, View view) { //加载取消的时候执行 } }, new ImageLoadingProgressListener() { @Override public void onProgressUpdate(String imageUri, View view, int current, int total) { //在这里更新 ProgressBar的进度信息,当前进度与总进度 , 如果是从缓存中获取的图片就不会执行该方法 } });
明确指定的访问本地图片:
String imageUri = "http://site.com/image.png"; //从网络获取 String imageUri = "file:///mnt/sdcard/image.png"; // 从SD card String imageUri = "content://media/external/audio/albumart/13"; //内容提供者 String imageUri = "assets://image.png"; // 访问工程中assets文件夹中的 String imageUri = "drawable://" + R.drawable.image; //访问drawables (only images, non-9patch)
GirdView,ListView加载图片, 滑动屏幕的时候停止下载图片
相信大部分人都是使用GridView,ListView来显示大量的图片,而当我们快速滑动GridView,ListView,我们希望能停止图片的加载,而在GridView,ListView停止滑动的时候加载当前界面的图片,这个框架当然也提供这个功能,使用起来也很简单,它提供了PauseOnScrollListener这个类来控制ListView,GridView滑动过程中停止去加载图片,该类使用的是代理模式
/** * 第一个参数就是我们的图片加载对象ImageLoader, * 第二个是控制是否在滑动过程中暂停加载图片,如果需要暂停传true就行了 * 第三个参数是控制猛的滑动界面的时候图片是否加载 */ listView.setOnScrollListener(new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling));
5.清除缓存
ImageLoader.getInstance().clearMemoryCache(); // 清除内存缓存 ImageLoader.getInstance().clearDiskCache(); // 清除本地缓存
注意事项:
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();