在一个小测试项目中,用到了110%能用到的ListView,因为大量的使用图片,导致的问题也就是大家很常见到的错位,复用,只能不断的去刷新数据和set相关参数,打Log会发现如果一个屏幕下的item个数为二或者更小,那么就会每两个一卡,哈哈哈,完全没有流畅的意思。于是看相关的,从图片压缩,到缓存机制以及等等,一个字有点意思,所以最终还是选择ImageLoader,可是ImageLoader也不是那么容易理解的,或者说每个人的理解可能都不一样。
1.导入 universal-image-loader-1.9.5.jar 包到libs目录下,右键 add 。。。
https://github.com/nostra13/Android-Universal-Image-Loader
2.增加网络访问权限和读取外部储存权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
其他权限如果需要可以看debug的提示,增加相应权限
3.初始化ImageLoader配置,放在在Application或者SplahActivity中,进行相关配置
ImageLoaderConfiguration config = new ImageLoaderConfiguration
.Builder(SplahActivity.this)
.memoryCacheExtraOptions(480, 800) // max width, max height,即保存的每个缓存文件的最大长宽
.threadPoolSize(3)//线程池内加载的数量
.threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024)) // You can pass your own memory cache implementation/你可以通过自己的内存缓存实现
.memoryCacheSize(2 * 1024 * 1024)
.discCacheSize(50 * 1024 * 1024)
.discCacheFileNameGenerator(new Md5FileNameGenerator())//将保存的时候的URI名称用MD5 加密
.tasksProcessingOrder(QueueProcessingType.LIFO)
.discCacheFileCount(100) //缓存的文件数量
.defaultDisplayImageOptions(DisplayImageOptions.createSimple())
.imageDownloader(new BaseImageDownloader(SplahActivity.this, 5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)超时时间
.writeDebugLogs() // Remove for release app
.build();//开始构建
有好多设置,这里仅仅是一些(SplahActivity.this ---> 即context上下文)
然后接着初始化,以上配置
ImageLoader.getInstance().init(config);//全局初始化此配置
4.在要使用ImageLoader的Activity中进行操作,初始化ImageLoader对象和显示配置参数
private ImageLoader imageLoader = ImageLoader.getInstance();
private DisplayImageOptions options;
5.对options进行初始化
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_launcher) //设置图片在下载期间显示的图片
.showImageForEmptyUri(R.drawable.ic_launcher)//设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.ic_launcher) //设置图片加载/解码过程中错误时候显示的图片
.cacheInMemory(true)//设置下载的图片是否缓存在内存中
.cacheOnDisc(true)//设置下载的图片是否缓存在SD卡中
.considerExifParams(true) //是否考虑JPEG图像EXIF参数(旋转,翻转)
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)//设置图片以如何的编码方式显示
.bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型//
//.delayBeforeLoading(int delayInMillis)//int delayInMillis为你设置的下载前的延迟时间
//设置图片加入缓存前,对bitmap进行设置
//.preProcessor(BitmapProcessor preProcessor)
.resetViewBeforeLoading(true)//设置图片在下载前是否重置,复位
.displayer(new RoundedBitmapDisplayer(20))//是否设置为圆角,弧度为多少
.displayer(new FadeInBitmapDisplayer(100))//是否图片加载好后渐入的动画时间
.build();//构建完成
6.设置图片链接:
String imageUri = "http://site.com/image.png"; // from Web
String imageUri = "file:///mnt/sdcard/image.png"; // from SD card
String imageUri = "content://media/external/audio/albumart/13"; // from content provider
String imageUri = "assets://image.png"; // from assets
String imageUri = "drawable://" + R.drawable.image; // from drawables (only images, non-9patch)
例:
public static final String[] ImagesUrl = new String[] {
// Heavy images
"http://7xl224.com1.z0.glb.clouddn.com/12.png",
"http://7xl224.com1.z0.glb.clouddn.com/1.jpg",
"http://7xl224.com1.z0.glb.clouddn.com/10.jpg",
"http://7xl224.com1.z0.glb.clouddn.com/11.jpg",
"http://7xl224.com1.z0.glb.clouddn.com/12.jpg"};
7.使用ImageLoader,前面我们已经声明了ImageLoader imageLoader,现在我们就使用该方法,在需要显示的地方
imageLoader.displayImage(ImagesUrl[position%5], holder.iv_main_title_img, options,new AnimateFirstDisplayListener());
(ImagesUrl[position%5]---对位置取余,使给出的Imagesurl 可以照顾到每一个position)
(holder.iv_main_title_img---即我们要显示的ImageView,此处为ListView用到的holder)
(传入参数options)
(一个ImageLoadingListener,可以直接new 这个也可以new一个我们定义的)
此处的AnimateFirstDisplayListener()为:
private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {
static final List<String> displayedImages = Collections.synchronizedList(new LinkedList<String>());
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
if (loadedImage != null) {
ImageView imageView = (ImageView) view;
// 是否第一次显示
boolean firstDisplay = !displayedImages.contains(imageUri);
if (firstDisplay) {
// 图片淡入效果
FadeInBitmapDisplayer.animate(imageView, 500);
displayedImages.add(imageUri);
}
}
}
}
8.至此我们就完成了ImageLoader的使用,很nice无卡顿无压抑,不过还需要做一些优化和设置,比如
8.1方法参数不一样的重载方法
a)
ImageLoader.getInstance().displayImage(imageUrl, imageView); // imageUrl代表图片的URL地址,imageView代表承载图片的IMAGEVIEW控件
b)
ImageLoader.getInstance().displayImage(imageUrl, imageView,options); // imageUrl代表图片的URL地址,imageView代表承载图片的IMAGEVIEW控件 , options代表DisplayImageOptions配置文件
c)
imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {
@Override
public void onLoadingStarted() {
//开始加载的时候执行
}
@Override
public void onLoadingFailed(FailReason failReason) {
//加载失败的时候执行
}
@Override
public void onLoadingComplete(Bitmap loadedImage) {
//加载成功的时候执行
}
@Override
public void onLoadingCancelled() {
//加载取消的时候执行
}});
d)
imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {
@Override
public void onLoadingStarted() {
//开始加载的时候执行
}
@Override
public void onLoadingFailed(FailReason failReason) {
//加载失败的时候执行
}
@Override
public void onLoadingComplete(Bitmap loadedImage) {
//加载成功的时候执行
}
@Override
public void onLoadingCancelled() {
//加载取消的时候执行
},new ImageLoadingProgressListener() {
@Override
public void onProgressUpdate(String imageUri, View view, int current,int total) {
//在这里更新 ProgressBar的进度信息
}
});
8.2设置默认图片:
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_launcher) //设置图片在下载期间显示的图片
.showImageForEmptyUri(R.drawable.ic_launcher)//设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.ic_launcher) //设置图片加载/解码过程中错误时候显示的图片
在我们设置options的时候注意一点就可了,替换成别的就ok了。
9.两个ImageLoader文章链接:
http://blog.csdn.net/wwj_748/article/details/10079311/
http://blog.csdn.net/vipzjyno1/article/details/23206387
(欢迎评论区研究讨论或者联系我一起学习,小王同学祝大家开心)