原:http://www.cnblogs.com/angeldevil/archive/2012/09/16/2687174.html

相关:https://github.com/nostra13/Android-Universal-Image-Loader

开发Android程序,一般情况下都会有两个操作,图片的异步加载与缓存,而图片的异步加载大都是从网络读取图片(还有生成本地图片缩略图等操作),为了减少网络操作,加快图片加载速度就需要对图片进行缓存,所以网上的好多图片异步加载方法都是与图片的缓存紧密关联的。但也有可能用户已经有了缓存的相关类库,这样使用起来就会有点麻烦。

最近一段处理跟图片相关的问题,本来是自己写的图片加载,不过有些状态的控制还是比较烦人的,比如ListView滚动时ImageView的重用,所以本着偷懒与充分利用现有资源的态度去网上搜罗图片异步加载的代码,最终在GreenDroid UI库中找到一个,其中有个AsyncImageView的自定义View用于异步加载图片,不过也像网上的大多数图片异步加载方法一样,是跟图片的缓存关联在一起的,不过只是很简单的内存缓存,无文件缓存。图片的加载方法也如其他的一样是写死了的,这就限制了其使用范围,只可通过InputStream来decode图片,而像生成缩略图或其他一些图片处理的异步处理就无法用途。修改现有类库总比自己从头写来的简单,于是稍微修改了下AsyncImageView,使其可以自定义缓存与图片加载方法,对于AsyncImageView只有一点点的修改,大都是别人源码。

1. 核心类

  • ImageLoader:图片加载核心类,内部使用线程池加载图片
  • ImageRequest:表示一个图片加载的请求
  • AsyncImageView:自定义的图片异步加载View
  • LoadMethod:自定义图片加载方法的接口,可以通过实现此接口来自定义图片的加载方法
  • CacheCallback:缓存接口,可以通过实现此接口实现对缓存的读写
  • AsyncImageView.OnImageViewLoadListener:图片加载状态监听(开始,失败,结束)

2. 图片加载方法

public void run() {

    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

    final Handler h = mHandler;
Bitmap bitmap = null;
Throwable throwable = null; h.sendMessage(Message.obtain(h, ON_START)); try {
if (TextUtils.isEmpty(mUrl)) {
throw new Exception("The given URL cannot be null or empty");
} // 如果自定义了加载方法,则用自定义的方法
if (mLoadMethod != null) {
bitmap = mLoadMethod.load(mUrl);
} else { InputStream inputStream = null; // Asset
if (mUrl.startsWith("file:///android_asset/")) {
inputStream = sAssetManager.open(mUrl.replaceFirst(
"file:///android_asset/", ""));
}
// File
else if (mUrl.startsWith("file:///") || mUrl.startsWith("/")) {
if (mUrl.startsWith("file:///"))
mUrl = mUrl.replaceFirst("file:///", "/");
inputStream = new FileInputStream(mUrl);
}
// NetWork
else {
// 在用URL类加载图片时,发现有的机型上面通过URL类获得的InputStream解析获得的图片总是null,故使用HttpClient
HttpGet httpRequest = new HttpGet(mUrl);
HttpClient httpclient = new DefaultHttpClient();
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
HttpConnectionParams.setSoTimeout(httpParams, 5000);
httpRequest.setParams(httpParams);
HttpResponse response = (HttpResponse)httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
InputStream instream = bufHttpEntity.getContent();
BufferedInputStream bi = new BufferedInputStream(instream);
inputStream = bi;
} // 虽然AsyncImageView中有设置BitmapFactory.Options的方法,但一般情况下都未知图片的大小,也就无法计算相应的inSampleSize,
// 也就无法设置相应的BitmapFactory.Options,所以一般情况下还是根据自己的需要自定义LoadMethod为好
bitmap = BitmapFactory.decodeStream(inputStream, null,
(mOptions == null) ? sDefaultOptions : mOptions);
inputStream.close();
}
if (mBitmapProcessor != null && bitmap != null) {
final Bitmap processedBitmap = mBitmapProcessor.processImage(bitmap);
if (processedBitmap != null) {
bitmap.recycle();
bitmap = processedBitmap;
}
} } catch (Exception e) {
Log.e(LOG_TAG, "Error while fetching image", e);
throwable = e;
} if (bitmap == null) {
if (throwable == null) {
throwable = new Exception("Skia image decoding failed");
}
h.sendMessage(Message.obtain(h, ON_FAIL, throwable));
} else {
h.sendMessage(Message.obtain(h, ON_END, bitmap));
if (mCache != null) {
mCache.writeCache(TextUtils.isEmpty(mCacheKey) ? mUrl : mCacheKey, bitmap);
}
}
}

如果自定义了LoadMethod,会调用相应的方法加载图片,如果没有自定义,会使用默认的加载方法,可以加载本地图片,Asset图片与网络图片,GreenDroid的源码中加载网络图片是用的URL的,但我们以前在加载网络图片时遇到一个问题,有的机型通过URL类获得的ImputStream解析图片总是返回null,所以就改为了HttpClient。

3.使用方法

通过AsyncImageView的setPath方法来加载图片,setPath有3个重载方法:

  • public void setPath(String path)
  • public void setPath(String path, LoadMethod loadMethod)
  • public void setPath(String path, LoadMethod loadMethod, String cacheKey)

第一个参数指定要加载的图片的路径,第二个参数为自定义的图片加载方法,若不指定则用默认的。

至于加第三个参数,是做缓存用的,一般要加载的图片的路径都是唯一的,所以一般用第一个参数来做为缓存的Key就行了,但也有特殊情况,比如读取局域网中的图片,一般都是自动获取IP,所以根据图片路径做为缓存的Key可能是不合适的,所以就需要根据需要手动指定用来作为缓存的Key。

/**
* 设置要加载的图片的路径, 可为网络路径, Asset文件路径(file:///android_asset), 本地图片路径(file:///或/)
*
* @param path 要加载的图片的路径, 若为null则加载默认图片
* @param loadMethod 自定义的图片加载的方法, 可以null, 使用默认的加载方法
* @param cacheKey 缓存key
*/
public void setPath(String path, LoadMethod loadMethod, String cacheKey) { // Check the url has changed
if (mBitmap != null && path != null && path.equals(mUrl)) { // TODO mBitmap != null necessary?
return;
} stopLoading();
mUrl = path;
mCacheKey = cacheKey;
mLoadMethod = loadMethod; // Setting the url to an empty string force the displayed image to the
// default image
if (TextUtils.isEmpty(mUrl)) {
mBitmap = null;
setDefaultImage();
} else {
if (!mPaused) {
reload();
} else {
// We're paused: let's look in a synchronous and efficient cache
// prior using the default image.
mBitmap = readCache(); // TODO 可能会耗时间
if (mBitmap != null) {
setImageBitmap(mBitmap);
} else {
setDefaultImage();
}
}
}
}
public void reload(boolean force) {
if (mRequest == null && mUrl != null) { // Prior downloading the image ... let's look in a cache !
mBitmap = null;
if (!force) {
// This may take a long time.
mBitmap = readCache();
} if (mBitmap != null) {
setImageBitmap(mBitmap);
return;
} setDefaultImage();
mRequest = new ImageRequest(mUrl, this, mImageProcessor, mOptions, mCacheKey);
mRequest.load(getContext(), mLoadMethod);
if (ImageLoader.getInstance() != null && ImageLoader.getInstance().getCache() == null) {
ImageLoader.getInstance().setCache(mCache);
}
}

readCache()用于读取缓存,代码如下:

    private Bitmap readCache() {
if (mCache != null)
return mCache.readCache(TextUtils.isEmpty(mCacheKey) ? mUrl : mCacheKey);
return null;
}

其中的mCache由用户能过setCacheCallback(CacheCallback callback)设置用户自定义的缓存方法,由此将图片的加载与缓存分离开,使用户可以使用现有的缓存实现。如要用户指定了缓存Key就使用用户指定的Key,否则就用图片的路径作Key。

4.AsyncImageView中的其他重要方法

  • reload([boolean force]):重新加载
  • stopLoading():停止加载,如果当前正在加载则没有效果,如果加载任务在加载线程池队列中则取消。
  • setDefaultImage...()类方法:设置默认图片。
  • setPause(boolean pause):是否加载图片

源码下载:AsyncImage

Android图片异步加载的更多相关文章

  1. Android 图片异步加载的体会,SoftReference已经不再适用

      在网络上搜索Android图片异步加载的相关文章,目前大部分提到的解决方案,都是采用Map<String, SoftReference<Drawable>>  这样软引用的 ...

  2. Android图片异步加载之Android-Universal-Image-Loader

    将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...

  3. Android图片异步加载之Android-Universal-Image-Loader(转)

    今天要介绍的是Github上一个使用非常广泛的图片异步加载库Android-Universal-Image-Loader,该项目的功能十分强大,可以说是我见过的目前功能最全.性能最优的图片异步加载解决 ...

  4. Android图片异步加载框架Android-Universal-Image-Loader

    版权声明:本文为博主原创文章,未经博主允许不得转载. Android-Universal-Image-Loader是一个图片异步加载,缓存和显示的框架.这个框架已经被很多开发者所使用,是最常用的几个 ...

  5. [置顶] Android图片异步加载之Android-Universal-Image-Loader

    将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...

  6. Android图片异步加载的方法

    很多时候,我们在加载大图片或者需要处理较多图像数据的时候,希望显示效果能好点,不至于因为图片解码耗时产生ANR等情况,不得不说异步加载是个不错的方法.说到异步加载,避免application出现ANR ...

  7. Android 图片异步加载 加载网络图片

    最近用到了加载网络图片,研究了一下,写一点简单的介绍: 首先创建一个线程去取图片(网络请求必须放在线程中): /** * 使用继承java.lang.Thread类的方式创建一个线程 * 直接取图片, ...

  8. Android ListView 图片异步加载和图片内存缓存

    开发Android应用经常需要处理图片的加载问题.因为图片一般都是存放在服务器端,需要联网去加载,而这又是一个比较耗时的过程,所以Android中都是通过开启一个异步线程去加载.为了增加用户体验,给用 ...

  9. Android新浪微博客户端(七)——ListView中的图片异步加载、缓存

    原文出自:方杰|http://fangjie.info/?p=193转载请注明出处 最终效果演示:http://fangjie.sinaapp.com/?page_id=54 该项目代码已经放到git ...

随机推荐

  1. 【刷题】BZOJ 1458 士兵占领

    Description 有一个M * N的棋盘,有的格子是障碍.现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵.我们称这些士兵占领了整个棋盘当满足第i行至少放 ...

  2. 搭建ELK收集Nginx日志

    众所周知,ELK是日志收集套装,这里就不多做介绍了. 画了一个粗略的架构图,如下: 这里实际用了三个节点,系统版本为CentOS6.6,ES版本为2.3.5,logstash版本为2.4.0,kiba ...

  3. NOIWC前的交流题目汇总

    RT 2018.12.27 i207M:BZOJ 4695 最假女选手 以维护最大值为例,记录最大值和严格次大值和最大值的出现次数,然后取min的时候递归到小于最大值但大于次大值修改,这个就是最重要的 ...

  4. bzoj 2178 自适应Simpson积分

    #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #i ...

  5. web服务器nginx和apache的对比分析

         今天准备较详细的对比一下apache httpd与nginx两个web服务器的异同点.优缺点.由于我并不是做web开发的,所以有什么理解错误还请指出,想要了解它们是因为工作中有时候会用到它, ...

  6. 预读(读取文件前几行)文件(txt,dat,csv等)程序

    需求: txt.dat.csv文件很大,需要花很长的时间打开, 但实际上我们只需要查看文件的前几行,查看数据的内容和格式 exe & code :  https://github.com/co ...

  7. 利用solr实现商品的搜索功能

      后期补充: 为什么要用solr服务,为什么要用luncence? 问题提出:当我们访问购物网站的时候,我们可以根据我们随意所想的内容输入关键字就可以查询出相关的内容,这是怎么做到呢?这些随意的数据 ...

  8. NATS_12:NATS Streaming详解

    NATS Streaming NATS Streaming是一个以NATS为驱动的数据流系统且它的源码也是由Golang语言编写的.其中NATS Streaming服务是一个可执行的文件名为:nats ...

  9. Java泛型底层源码解析--ConcurrentHashMap(JDK1.7)

    1. Concurrent相关历史 JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全 ...

  10. 获取异常信息e.printStackTrace()的内容

    获取异常信息e.printStackTrace()的内容 最近做项目的时候需要记录操作的日志,但是记录异常信息的是发现使用e.getMessage()根本无法满足需要,并且e.getMessage() ...