android异步加载图片类(续)-universal-image-loader详解

2024-06-06 11:58

本文主要是介绍android异步加载图片类(续)-universal-image-loader详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前写过一篇android异步加载图片类 ,后来接触了一个开源项目universal-image-loader,听说淘宝也是用这玩意

发现自己写的那个异步加载类太简单了,虽然功能是实现了,但是很多优化的问题都没有解决

比如:

同一个ui加载同一张图,会出现只加载一张,其他的加载不了

加载多图的时候会有oom等问题


现在来说说universal-image-loader

特点:

多线程的图像加载
的可能性的宽调谐对ImageLoader的配置(线程池的大小,HTTP选项,内存和光盘高速缓存,显示图像,以及其他)
的图像的可能性中的缓存存储器和/或设备的文件器系统(或SD卡)
可以“听”加载过程中
可自定义每个显示的图像调用分隔的选项
Widget支持
Android 1.5以上支持


使用方法:(我自己封装了一个类ImgConfig使用,方便一些)

只需两步即可加载网络图片:

一、初始化

ImgConfig.initImageLoader();

二、

ImgConfig.showUserSImg(imgUrl, imageview); //图片的url,要显示的view


以下是我自己写的ImgConfig,仅供参考:

public class ImgConfig extends ImageLoader {
private static DisplayImageOptions options_corner;
private static DisplayImageOptions options_square;
private static AnimateFirstDisplayListener animateFirstDisplayListener = new AnimateFirstDisplayListener();
/**
* @param url   服务器的文件名
* @param imageView
*            显示方形图片 S for Square
*/
public static void showUserSImg(String url, ImageView imageView) {
ImageLoader.getInstance().displayImage(url,
imageView, options_square, animateFirstDisplayListener);
}
/**
* @param url   服务器的文件名
* @param imageView
*            圆角 C for Corner
*/
public static void showUserCImg(String url, ImageView imageView) {
ImageLoader.getInstance().displayImage(url,
imageView, options_corner, animateFirstDisplayListener);
}
/**
* 初始化图片读取方式
*/
public static void initImageLoader() {
DisplayImageOptions options_corner = new DisplayImageOptions.Builder()
.showImageOnLoading(ImgHandler.ToCircular(R.drawable.defult_head))
// 加载中
.showImageForEmptyUri(ImgHandler.ToCircular(R.drawable.defult_head))
// 空uri
.showImageOnFail(ImgHandler.ToCircular(R.drawable.defult_head))
// 失败时
.cacheInMemory(true)
// 设置下载的图片是否缓存在内存中
.cacheOnDisc(true)
// 设置下载的图片是否缓存在SD卡中
.considerExifParams(true)
.displayer(new RoundedBitmapDisplayer(10)) // 展现方式:圆角
.resetViewBeforeLoading(true)
.imageScaleType(ImageScaleType.EXACTLY)
// new FadeInBitmapDisplayer(300) 渐现
.build();
options_square = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.defult_head)
.showImageForEmptyUri(R.drawable.defult_head)
.showImageOnFail(R.drawable.defult_head)
.cacheInMemory(true)
.cacheOnDisc(true)
.considerExifParams(true)
.displayer(new FadeInBitmapDisplayer(100)) // 展现方式:渐现
.resetViewBeforeLoading(true)
.imageScaleType(ImageScaleType.EXACTLY)
.build();
// This configuration tuning is custom. You can tune every option, you
// may tune some of them,
// or you can create default configuration by
// ImageLoaderConfiguration.createDefault(this);
// method.
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
ContextUtil.getInstance())
.threadPriority(Thread.NORM_PRIORITY)  //线程池的数量
.denyCacheImageMultipleSizesInMemory() // 不同大小图片只有一个缓存,默认多个
.tasksProcessingOrder(QueueProcessingType.LIFO)
// 设置图片下载和显示的工作队列排序
.discCache(new LimitedAgeDiscCache(new File(Constant.SAVE_IMG_PATH),
new Md5FileNameGenerator(), 7 * 24 * 60 * 60)) // 7天自动清除,按秒算
// .writeDebugLogs() // Remove for release app
.imageDownloader(     //或许你的服务器有特定的加载图的方式,在这里实现
new BaseImageDownloader(ContextUtil.getInstance()) {
@Override
public InputStream getStream(String imageUri,
Object extra) throws IOException {
return super.getStream(imageUri, extra);
}
@Override
protected InputStream getStreamFromNetwork(
String imageUri, Object extra)
throws IOException {
HttpURLConnection conn = createConnection(
imageUri, extra);
int redirectCount = 0;
while (conn.getResponseCode() / 100 == 3
&& redirectCount < MAX_REDIRECT_COUNT) {
conn = createConnection(
conn.getHeaderField("Location"),
extra);
redirectCount++;
}
InputStream imageStream = null;
try {
imageStream = conn.getInputStream();
} catch (IOException e) {
// Read all data to allow reuse connection
// (http://bit.ly/1ad35PY)
IoUtils.readAndCloseStream(conn
.getErrorStream());
}
return new ContentLengthInputStream(
new BufferedInputStream(imageStream,
BUFFER_SIZE), conn
.getContentLength());
}
}).build();
// Initialize ImageLoader with configuration.  初始化
ImageLoader.getInstance().init(config);
}
/**
* @author Administrator 监听读取完图片
*/
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);
}
}
}
}
}

特别提示以下 .disCache() 和 .imageDownloader

因为我不想要自动帮我加密文件,所以我.disCache() 里面的加密方法 new Md5FileNameGenerator()

换成了

new FileNameGenerator() {
@Override
public String generate(String imageUri) {
return FileUtil.getFileName(imageUri);
}
}

服务器有自己的加载方式,我把加载 .imageDownloader的加载图片方法换了

new BaseImageDownloader(ContextUtil.getInstance()) {
@Override
public InputStream getStream(String imageUri,
Object extra) throws IOException {
return super.getStream(imageUri, extra);
}
@Override
protected InputStream getStreamFromNetwork(
String imageUri, Object extra)
throws IOException {
HttpURLConnection conn = createConnection(
imageUri, extra);
int redirectCount = 0;
while (conn.getResponseCode() / 100 == 3
&& redirectCount < MAX_REDIRECT_COUNT) {
conn = createConnection(
conn.getHeaderField("Location"),
extra);
redirectCount++;
}
InputStream imageStream = null;
try {
imageStream = conn.getInputStream();
} catch (IOException e) {
// Read all data to allow reuse connection
// (http://bit.ly/1ad35PY)
IoUtils.readAndCloseStream(conn
.getErrorStream());
}
return new ContentLengthInputStream(
new BufferedInputStream(imageStream,
BUFFER_SIZE), conn
.getContentLength());
}
}


总结: universal-image-loader 这个开源项目很好用,

研究了一下源码,有很多启发,扩展性很好,值得学习

官方提供的例子: universal-image-loader例子


这篇关于android异步加载图片类(续)-universal-image-loader详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1036045

相关文章

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

SQL Server 中的 WITH (NOLOCK) 示例详解

《SQLServer中的WITH(NOLOCK)示例详解》SQLServer中的WITH(NOLOCK)是一种表提示,等同于READUNCOMMITTED隔离级别,允许查询在不获取共享锁的情... 目录SQL Server 中的 WITH (NOLOCK) 详解一、WITH (NOLOCK) 的本质二、工作

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (

Java Thread中join方法使用举例详解

《JavaThread中join方法使用举例详解》JavaThread中join()方法主要是让调用改方法的thread完成run方法里面的东西后,在执行join()方法后面的代码,这篇文章主要介绍... 目录前言1.join()方法的定义和作用2.join()方法的三个重载版本3.join()方法的工作原

Spring AI使用tool Calling和MCP的示例详解

《SpringAI使用toolCalling和MCP的示例详解》SpringAI1.0.0.M6引入ToolCalling与MCP协议,提升AI与工具交互的扩展性与标准化,支持信息检索、行动执行等... 目录深入探索 Spring AI聊天接口示例Function CallingMCPSTDIOSSE结束语