异步下载网络图片,并提供是否缓存至内存或外部文件的功能

异步加载类AsyncImageLoader

public void downloadImage(final String url, final ImageCallback callback);

public void downloadImage(final String url, final boolean cache2Memory, final ImageCallback callback);

public void setCache2File(boolean flag);

public void setCachedDir(String dir);

图片下载和缓存实现类LoaderImpl

1.AsyncImageLoader.java

 package com.imagecache;

 import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.util.Log; public class AsyncImageLoader {
//保存正在下载的图片URL集合,避免重复下载用
private static HashSet<String> sDownloadingSet;
//软引用内存缓存
private static Map<String,SoftReference<Bitmap>> sImageCache;
//图片三种获取方式管理者,网络URL获取、内存缓存获取、外部文件缓存获取
private static LoaderImpl impl;
//线程池相关
private static ExecutorService sExecutorService; //通知UI线程图片获取ok时使用
private Handler handler; /**
* 异步加载图片完毕的回调接口
*/
public interface ImageCallback{
/**
* 回调函数
* @param bitmap: may be null!
* @param imageUrl
*/
public void onImageLoaded(Bitmap bitmap, String imageUrl);
} static{
sDownloadingSet = new HashSet<String>();
sImageCache = new HashMap<String,SoftReference<Bitmap>>();
impl = new LoaderImpl(sImageCache);
} public AsyncImageLoader(Context context){
handler = new Handler();
startThreadPoolIfNecessary(); String defaultDir = context.getCacheDir().getAbsolutePath();
setCachedDir(defaultDir);
} /**
* 是否缓存图片至/data/data/package/cache/目录
* 默认不缓存
*/
public void setCache2File(boolean flag){
impl.setCache2File(flag);
} /**
* 设置缓存路径,setCache2File(true)时有效
*/
public void setCachedDir(String dir){
impl.setCachedDir(dir);
} /**开启线程池*/
public static void startThreadPoolIfNecessary(){
if(sExecutorService == null || sExecutorService.isShutdown() || sExecutorService.isTerminated()){
sExecutorService = Executors.newFixedThreadPool(3);
//sExecutorService = Executors.newSingleThreadExecutor();
}
} /**
* 异步下载图片,并缓存到memory中
* @param url
* @param callback see ImageCallback interface
*/
public void downloadImage(final String url, final ImageCallback callback){
downloadImage(url, true, callback);
} /**
*
* @param url
* @param cache2Memory 是否缓存至memory中
* @param callback
*/
public void downloadImage(final String url, final boolean cache2Memory, final ImageCallback callback){
if(sDownloadingSet.contains(url)){
Log.i("AsyncImageLoader", "###该图片正在下载,不能重复下载!");
return;
} Bitmap bitmap = impl.getBitmapFromMemory(url);
if(bitmap != null){
if(callback != null){
callback.onImageLoaded(bitmap, url);
}
}else{
//从网络端下载图片
sDownloadingSet.add(url);
sExecutorService.submit(new Runnable(){
@Override
public void run() {
final Bitmap bitmap = impl.getBitmapFromUrl(url, cache2Memory);
handler.post(new Runnable(){
@Override
public void run(){
if(callback != null)
callback.onImageLoaded(bitmap, url);
sDownloadingSet.remove(url);
}
});
}
});
}
} /**
* 预加载下一张图片,缓存至memory中
* @param url
*/
public void preLoadNextImage(final String url){
//将callback置为空,只将bitmap缓存到memory即可。
downloadImage(url, null);
} }

2.LoaderImpl.java

 package com.imagecache;

 import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; /**
*
* @author Administrator
* @desc 异步加载图片管理器
*
*/
public class LoaderImpl {
//内存中的软应用缓存
private Map<String, SoftReference<Bitmap>> imageCache; //是否缓存图片至本地文件
private boolean cache2FileFlag = false; //缓存目录,默认是/data/data/package/cache/目录
private String cachedDir; public LoaderImpl(Map<String, SoftReference<Bitmap>> imageCache){
this.imageCache = imageCache;
} /**
* 是否缓存图片至外部文件
* @param flag
*/
public void setCache2File(boolean flag){
cache2FileFlag = flag;
} /**
* 设置缓存图片到外部文件的路径
* @param cacheDir
*/
public void setCachedDir(String cacheDir){
this.cachedDir = cacheDir;
} /**
* 从网络端下载图片
* @param url 网络图片的URL地址
* @param cache2Memory 是否缓存(缓存在内存中)
* @return bitmap 图片bitmap结构
*
*/
public Bitmap getBitmapFromUrl(String url, boolean cache2Memory){
Bitmap bitmap = null;
try{
URL u = new URL(url);
HttpURLConnection conn = (HttpURLConnection)u.openConnection();
InputStream is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is); if(cache2Memory){
//1.缓存bitmap至内存软引用中
imageCache.put(url, new SoftReference<Bitmap>(bitmap));
if(cache2FileFlag){
//2.缓存bitmap至/data/data/packageName/cache/文件夹中
String fileName = getMD5Str(url);
String filePath = this.cachedDir + "/" +fileName;
FileOutputStream fos = new FileOutputStream(filePath);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
}
} is.close();
conn.disconnect();
return bitmap;
}catch(IOException e){
e.printStackTrace();
return null;
}
} /**
* 从内存缓存中获取bitmap
* @param url
* @return bitmap or null.
*/
public Bitmap getBitmapFromMemory(String url){
Bitmap bitmap = null;
if(imageCache.containsKey(url)){
synchronized(imageCache){
SoftReference<Bitmap> bitmapRef = imageCache.get(url);
if(bitmapRef != null){
bitmap = bitmapRef.get();
return bitmap;
}
}
}
//从外部缓存文件读取
if(cache2FileFlag){
bitmap = getBitmapFromFile(url);
if(bitmap != null)
imageCache.put(url, new SoftReference<Bitmap>(bitmap));
} return bitmap;
} /**
* 从外部文件缓存中获取bitmap
* @param url
* @return
*/
private Bitmap getBitmapFromFile(String url){
Bitmap bitmap = null;
String fileName = getMD5Str(url);
if(fileName == null)
return null; String filePath = cachedDir + "/" + fileName; try {
FileInputStream fis = new FileInputStream(filePath);
bitmap = BitmapFactory.decodeStream(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
bitmap = null;
}
return bitmap;
} /**
* MD5 加密
*/
private static String getMD5Str(String str) {
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(str.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
System.out.println("NoSuchAlgorithmException caught!");
return null;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
} byte[] byteArray = messageDigest.digest();
StringBuffer md5StrBuff = new StringBuffer();
for (int i = 0; i < byteArray.length; i++) {
if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
else
md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
} return md5StrBuff.toString();
} /**
* MD5 加密
private static String getMD5Str(Object...objects){
StringBuilder stringBuilder=new StringBuilder();
for (Object object : objects) {
stringBuilder.append(object.toString());
}
return getMD5Str(stringBuilder.toString());
}*/
}

3.测试Activity

 package com.imagecache;

 import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.widget.ImageView; public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); final ImageView iv = (ImageView)findViewById(R.id.iv);
//网络图片地址
String imgUrl = "http://..."; //for test
AsyncImageLoader loader = new AsyncImageLoader(getApplicationContext()); //将图片缓存至外部文件中
loader.setCache2File(true); //false
//设置外部缓存文件夹
loader.setCachedDir(this.getCacheDir().getAbsolutePath()); //下载图片,第二个参数是否缓存至内存中
loader.downloadImage(imgUrl, true/*false*/, new AsyncImageLoader.ImageCallback() {
@Override
public void onImageLoaded(Bitmap bitmap, String imageUrl) {
if(bitmap != null){
iv.setImageBitmap(bitmap);
}else{
//下载失败,设置默认图片
}
}
});
} }

android 下载网络图片并缓存的更多相关文章

  1. android下载网络图片并缓存

    异步下载网络图片,并提供是否缓存至内存或外部文件的功能 异步加载类AsyncImageLoader public void downloadImage(final String url, final ...

  2. Android 下载网络图片保存到本地

    通过网络地址获取网络图片,点击下载将图片显示出来,然后点击图片将图片保存到本地. 首先需要在manifest上添加一些权限: <!-- 访问网络的权限 --> <uses-permi ...

  3. android下载网络图片,设置宽高,等比缩放

    使用Picasso组件去下载图片会发现图片宽高会变形不受等比缩放控制,即使设置了图片的 scaleType,可能是对Picasso的api没有用对, Picasso.with(this.activit ...

  4. Android开发-下载网络图片并显示到本地

    Android下载网络图片的流程是: 发送网络请求->将图片以流的形式下载下来->将流转换为Bitmap并赋给ImageView控件. 注意点 最新的Android系统不可以在主线程上请求 ...

  5. wemall app商城源码Android之ListView异步加载网络图片(优化缓存机制)

    wemall-mobile是基于WeMall的android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.本文分享wemall app商城源码Android之L ...

  6. Android异步下载图片并且缓存图片到本地

    Android异步下载图片并且缓存图片到本地 在Android开发中我们经常有这样的需求,从服务器上下载xml或者JSON类型的数据,其中包括一些图片资源,本demo模拟了这个需求,从网络上加载XML ...

  7. (14)[Xamarin.Android] 异步的网络图片下载

    原文 [Xamarin.Android] 异步的网络图片下载 在设计要从网络上接大量数据并且显示在Android Listview中,而这些资料是利用Json格式传送并且数据中包含这图片档案. 那在X ...

  8. (BUG已修改,最优化)安卓ListView异步加载网络图片与缓存软引用图片,线程池,只加载当前屏之说明

    原文:http://blog.csdn.net/java_jh/article/details/20068915 迟点出更新的.这个还有BUG.因为软引应不给力了.2.3之后 前几天的原文有一个线程管 ...

  9. Android之网络图片加载的5种基本方式

    学了这么久,最近有空把自己用到过的网络加载图片的方式总结了出来,与大家共享,希望对你们有帮助. 此博客包含Android 5种基本的加载网络图片方式,包括普通加载HttpURLConnection.H ...

随机推荐

  1. Android 65K问题之Multidex原理分析及NoClassDefFoundError的解决方法

    Android 65K问题相信困惑了不少人,尽管AS的出来能够通过分dex高速解决65K问题,可是同一时候也easy由于某些代码没有打包到MainDex里引起NoClassDefFoundError. ...

  2. 软件project文档中的数据库模型设计

    背景:软件project文档之<数据库设计说明书>的结构设计部分要明白规划出数据库的概念结构设计.逻辑结构设计.物理结构设计,就是设计数据库的概念模型.逻辑模型.物理模型.那么.何为数据库 ...

  3. 表现与数据分离;前台MVC

    无意间看到一个web前端招聘要求:表现与数据分离 这名词对我非常陌生,我就去百度了下 由于有各种莫名其妙的需求,所以才会出现我们前端MVC这样的莫名其妙的东西... 我们的html就是model,我们 ...

  4. Android之自己定义(上方标题随ViewPager手势慢慢滑动)

    近期非常蛋疼,项目要模仿网易新闻的样式去做.上次把仿网易新闻client的下拉刷新写出来了.这次是ViewPager的滑动,同一时候ViewPager的上面标题下划线尾随者移动.本来通过ViewPag ...

  5. oc43--野指针和空指针

    // // main.m // 野指针和空指针 #import <Foundation/Foundation.h> #import "Person.h" int mai ...

  6. oc36--自定义构造方法在继承中的表现

    // // Person.h #import <Foundation/Foundation.h> @interface Person : NSObject @property int ag ...

  7. hdu 2177(威佐夫博奕+打表)

    取(2堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  8. C++ 中的友元(friend)

    首先友元不是一个好的设计,它破坏了封装.并且自身有很多局限:比如友元关系不能被继承:友元关系是单向的,不具有交换性:友元关系不具有传递性. 类内声明的 friend 变量(或者函数)在访问该类的成员时 ...

  9. 可持久化Treap(fhq Treap,非旋转式Treap)学习(未完待续)

    简介:     Treap,一种表现优异的BST 优势:     其较于AVL.红黑树实现简单,浅显易懂     较于Splay常数小,通常用于树套BST表现远远优于Splay     或许有人想说S ...

  10. Spring 的优秀工具类盘点---转

    第 1 部分: 文件资源操作和 Web 相关工具类 http://www.ibm.com/developerworks/cn/java/j-lo-spring-utils1/ 文件资源操作 文件资源的 ...