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

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

  1. package com.imagecache;
  2. import java.lang.ref.SoftReference;
  3. import java.util.HashMap;
  4. import java.util.HashSet;
  5. import java.util.Map;
  6. import java.util.concurrent.ExecutorService;
  7. import java.util.concurrent.Executors;
  8. import android.content.Context;
  9. import android.graphics.Bitmap;
  10. import android.os.Handler;
  11. import android.util.Log;
  12. public class AsyncImageLoader {
  13. //保存正在下载的图片URL集合,避免重复下载用
  14. private static HashSet<String> sDownloadingSet;
  15. //软引用内存缓存
  16. private static Map<String,SoftReference<Bitmap>> sImageCache;
  17. //图片三种获取方式管理者,网络URL获取、内存缓存获取、外部文件缓存获取
  18. private static LoaderImpl impl;
  19. //线程池相关
  20. private static ExecutorService sExecutorService;
  21. //通知UI线程图片获取ok时使用
  22. private Handler handler;
  23. /**
  24. * 异步加载图片完毕的回调接口
  25. */
  26. public interface ImageCallback{
  27. /**
  28. * 回调函数
  29. * @param bitmap: may be null!
  30. * @param imageUrl
  31. */
  32. public void onImageLoaded(Bitmap bitmap, String imageUrl);
  33. }
  34. static{
  35. sDownloadingSet = new HashSet<String>();
  36. sImageCache = new HashMap<String,SoftReference<Bitmap>>();
  37. impl = new LoaderImpl(sImageCache);
  38. }
  39. public AsyncImageLoader(Context context){
  40. handler = new Handler();
  41. startThreadPoolIfNecessary();
  42. String defaultDir = context.getCacheDir().getAbsolutePath();
  43. setCachedDir(defaultDir);
  44. }
  45. /**
  46. * 是否缓存图片至/data/data/package/cache/目录
  47. * 默认不缓存
  48. */
  49. public void setCache2File(boolean flag){
  50. impl.setCache2File(flag);
  51. }
  52. /**
  53. * 设置缓存路径,setCache2File(true)时有效
  54. */
  55. public void setCachedDir(String dir){
  56. impl.setCachedDir(dir);
  57. }
  58. /**开启线程池*/
  59. public static void startThreadPoolIfNecessary(){
  60. if(sExecutorService == null || sExecutorService.isShutdown() || sExecutorService.isTerminated()){
  61. sExecutorService = Executors.newFixedThreadPool(3);
  62. //sExecutorService = Executors.newSingleThreadExecutor();
  63. }
  64. }
  65. /**
  66. * 异步下载图片,并缓存到memory中
  67. * @param url
  68. * @param callback  see ImageCallback interface
  69. */
  70. public void downloadImage(final String url, final ImageCallback callback){
  71. downloadImage(url, true, callback);
  72. }
  73. /**
  74. *
  75. * @param url
  76. * @param cache2Memory 是否缓存至memory中
  77. * @param callback
  78. */
  79. public void downloadImage(final String url, final boolean cache2Memory, final ImageCallback callback){
  80. if(sDownloadingSet.contains(url)){
  81. Log.i("AsyncImageLoader", "###该图片正在下载,不能重复下载!");
  82. return;
  83. }
  84. Bitmap bitmap = impl.getBitmapFromMemory(url);
  85. if(bitmap != null){
  86. if(callback != null){
  87. callback.onImageLoaded(bitmap, url);
  88. }
  89. }else{
  90. //从网络端下载图片
  91. sDownloadingSet.add(url);
  92. sExecutorService.submit(new Runnable(){
  93. @Override
  94. public void run() {
  95. final Bitmap bitmap = impl.getBitmapFromUrl(url, cache2Memory);
  96. handler.post(new Runnable(){
  97. @Override
  98. public void run(){
  99. if(callback != null)
  100. callback.onImageLoaded(bitmap, url);
  101. sDownloadingSet.remove(url);
  102. }
  103. });
  104. }
  105. });
  106. }
  107. }
  108. /**
  109. * 预加载下一张图片,缓存至memory中
  110. * @param url
  111. */
  112. public void preLoadNextImage(final String url){
  113. //将callback置为空,只将bitmap缓存到memory即可。
  114. downloadImage(url, null);
  115. }
  116. }

2.LoaderImpl.java

  1. package com.imagecache;
  2. import java.io.FileInputStream;
  3. import java.io.FileNotFoundException;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.io.UnsupportedEncodingException;
  8. import java.lang.ref.SoftReference;
  9. import java.net.HttpURLConnection;
  10. import java.net.URL;
  11. import java.security.MessageDigest;
  12. import java.security.NoSuchAlgorithmException;
  13. import java.util.Map;
  14. import android.graphics.Bitmap;
  15. import android.graphics.BitmapFactory;
  16. /**
  17. *
  18. * @author Administrator
  19. * @desc 异步加载图片管理器
  20. *
  21. */
  22. public class LoaderImpl {
  23. //内存中的软应用缓存
  24. private Map<String, SoftReference<Bitmap>> imageCache;
  25. //是否缓存图片至本地文件
  26. private boolean cache2FileFlag = false;
  27. //缓存目录,默认是/data/data/package/cache/目录
  28. private String cachedDir;
  29. public LoaderImpl(Map<String, SoftReference<Bitmap>> imageCache){
  30. this.imageCache = imageCache;
  31. }
  32. /**
  33. * 是否缓存图片至外部文件
  34. * @param flag
  35. */
  36. public void setCache2File(boolean flag){
  37. cache2FileFlag = flag;
  38. }
  39. /**
  40. * 设置缓存图片到外部文件的路径
  41. * @param cacheDir
  42. */
  43. public void setCachedDir(String cacheDir){
  44. this.cachedDir = cacheDir;
  45. }
  46. /**
  47. * 从网络端下载图片
  48. * @param url 网络图片的URL地址
  49. * @param cache2Memory 是否缓存(缓存在内存中)
  50. * @return bitmap 图片bitmap结构
  51. *
  52. */
  53. public Bitmap getBitmapFromUrl(String url, boolean cache2Memory){
  54. Bitmap bitmap = null;
  55. try{
  56. URL u = new URL(url);
  57. HttpURLConnection conn = (HttpURLConnection)u.openConnection();
  58. InputStream is = conn.getInputStream();
  59. bitmap = BitmapFactory.decodeStream(is);
  60. if(cache2Memory){
  61. //1.缓存bitmap至内存软引用中
  62. imageCache.put(url, new SoftReference<Bitmap>(bitmap));
  63. if(cache2FileFlag){
  64. //2.缓存bitmap至/data/data/packageName/cache/文件夹中
  65. String fileName = getMD5Str(url);
  66. String filePath = this.cachedDir + "/" +fileName;
  67. FileOutputStream fos = new FileOutputStream(filePath);
  68. bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
  69. }
  70. }
  71. is.close();
  72. conn.disconnect();
  73. return bitmap;
  74. }catch(IOException e){
  75. e.printStackTrace();
  76. return null;
  77. }
  78. }
  79. /**
  80. * 从内存缓存中获取bitmap
  81. * @param url
  82. * @return bitmap or null.
  83. */
  84. public Bitmap getBitmapFromMemory(String url){
  85. Bitmap bitmap = null;
  86. if(imageCache.containsKey(url)){
  87. synchronized(imageCache){
  88. SoftReference<Bitmap> bitmapRef = imageCache.get(url);
  89. if(bitmapRef != null){
  90. bitmap = bitmapRef.get();
  91. return bitmap;
  92. }
  93. }
  94. }
  95. //从外部缓存文件读取
  96. if(cache2FileFlag){
  97. bitmap = getBitmapFromFile(url);
  98. if(bitmap != null)
  99. imageCache.put(url, new SoftReference<Bitmap>(bitmap));
  100. }
  101. return bitmap;
  102. }
  103. /**
  104. * 从外部文件缓存中获取bitmap
  105. * @param url
  106. * @return
  107. */
  108. private Bitmap getBitmapFromFile(String url){
  109. Bitmap bitmap = null;
  110. String fileName = getMD5Str(url);
  111. if(fileName == null)
  112. return null;
  113. String filePath = cachedDir + "/" + fileName;
  114. try {
  115. FileInputStream fis = new FileInputStream(filePath);
  116. bitmap = BitmapFactory.decodeStream(fis);
  117. } catch (FileNotFoundException e) {
  118. e.printStackTrace();
  119. bitmap = null;
  120. }
  121. return bitmap;
  122. }
  123. /**
  124. * MD5 加密
  125. */
  126. private static String getMD5Str(String str) {
  127. MessageDigest messageDigest = null;
  128. try {
  129. messageDigest = MessageDigest.getInstance("MD5");
  130. messageDigest.reset();
  131. messageDigest.update(str.getBytes("UTF-8"));
  132. } catch (NoSuchAlgorithmException e) {
  133. System.out.println("NoSuchAlgorithmException caught!");
  134. return null;
  135. } catch (UnsupportedEncodingException e) {
  136. e.printStackTrace();
  137. return null;
  138. }
  139. byte[] byteArray = messageDigest.digest();
  140. StringBuffer md5StrBuff = new StringBuffer();
  141. for (int i = 0; i < byteArray.length; i++) {
  142. if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
  143. md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
  144. else
  145. md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
  146. }
  147. return md5StrBuff.toString();
  148. }
  149. /**
  150. * MD5 加密
  151. private static String getMD5Str(Object...objects){
  152. StringBuilder stringBuilder=new StringBuilder();
  153. for (Object object : objects) {
  154. stringBuilder.append(object.toString());
  155. }
  156. return getMD5Str(stringBuilder.toString());
  157. }*/
  158. }

3.测试Activity

    1. package com.imagecache;
    2. import android.app.Activity;
    3. import android.graphics.Bitmap;
    4. import android.os.Bundle;
    5. import android.widget.ImageView;
    6. public class MainActivity extends Activity {
    7. /** Called when the activity is first created. */
    8. @Override
    9. public void onCreate(Bundle savedInstanceState) {
    10. super.onCreate(savedInstanceState);
    11. setContentView(R.layout.main);
    12. final ImageView iv = (ImageView)findViewById(R.id.iv);
    13. //网络图片地址
    14. String imgUrl = "http://...";
    15. //for test
    16. AsyncImageLoader loader = new AsyncImageLoader(getApplicationContext());
    17. //将图片缓存至外部文件中
    18. loader.setCache2File(true); //false
    19. //设置外部缓存文件夹
    20. loader.setCachedDir(this.getCacheDir().getAbsolutePath());
    21. //下载图片,第二个参数是否缓存至内存中
    22. loader.downloadImage(imgUrl, true/*false*/, new AsyncImageLoader.ImageCallback() {
    23. @Override
    24. public void onImageLoaded(Bitmap bitmap, String imageUrl) {
    25. if(bitmap != null){
    26. iv.setImageBitmap(bitmap);
    27. }else{
    28. //下载失败,设置默认图片
    29. }
    30. }
    31. });
    32. }
    33. }

转自:http://blog.csdn.net/liliang497/article/details/7221110

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. C#获取类名为Internet_Explorer_Server控件的内容

    为了让大家都能够使用demo,我以IE为测试对象,另外为了突出重点,所以如何获取窗口句柄我就不做演示了(不清楚的童鞋,可以去Google下哈),句柄值我使用spy++获得 大家可以下载demo(附:s ...

  2. LINUX 修改SSH默认22端口的方法

    首先修改配置文件 vi /etc/ssh/sshd_config 找到#Port 22一段,这里是标识默认使用22端口,修改为如下: Port 22 Port 50000 然后保存退出 执行/etc/ ...

  3. 深入学习 FutureTask

    原文出处: 天凉好个秋 第一部分:What 在Java中一般通过继承Thread类或者实现Runnable接口这两种方式来创建多线程,但是这两种方式都有个缺陷,就是不能在执行完成后获取执行的结果,因此 ...

  4. linux设置预留端口号,防止监听端口被占用 ip_local_reserved_ports

    1. 背景 linux服务器启动时,会对指定的端口进行监听bind,如果同一个机器上这个端口已经被使用,则监听失败,程序无法启动. linux客户端连接服务器accept时,系统会分配本地临时端口用于 ...

  5. vim IDE配置

    参考: http://www.cnblogs.com/witcxc/archive/2011/12/28/2304704.html http://www.cnblogs.com/ma6174/arch ...

  6. hadoop from rookie to ninja - 1. Basic Architecture(基础架构)

    1. Daemons(守护进程) 新老架构 老的: Apache Hadoop 1.x (MRv1)   新的: Apache Hadoop 2.x (YARN)-Yet Another Resour ...

  7. IDEA使用笔记(七)——编辑器最大个数的设置

    我想一定有许多人和我一样在使用IDEA的时候,打开了许多的编辑器选项卡,但是打开的数量是有限的,我们想打开更多的页面,并且希望控制当再次达到大限的时候能关闭那些我们最久没有看的文件! 好吧!看下面的配 ...

  8. python工具 - 批量文件重命名

    日常工作中经常会遇到这样的情况,需要将某个文件夹下的文件按着一定的规则进行重命名,当文件数量及其庞大的时候手工一个一个的去修需要耗费大量的时间,以下python工具可以协助批量修改文件名. 场景:某文 ...

  9. [APM] 解读APM技术分类和实现方式

    在讲了APM的历史.作用和实际案例之后,下面我们来了解一下APM技术分类和实现方式以及它未来的发展趋势.在这之前,我们首先需要了解一下典型的互联网或移动互联网应用的整个应用交付链. 图1 上面这张示意 ...

  10. 【iCore1S 双核心板_ARM】例程五:IWDG看门狗实验——复位ARM

    实验原理: STM32内部包含独立看门狗,通过看门狗可以监控程序运行,程序错误 时,未在规定时间喂狗,自动复位ARM.本实验通过按键按下,停止喂狗, 制造程序运行 错误,从而产生复位 . 实验现象: ...