您的位置:首页 > 理论基础 > 计算机网络

android下载网络图片并缓存

2014-02-12 10:58 337 查看
异步下载网络图片,并提供是否缓存至内存或外部文件的功能

异步加载类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

[java] view
plaincopy

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

[java] view
plaincopy

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

[java] view
plaincopy

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{

//下载失败,设置默认图片

}

}

});

}



}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: