android下载网络图片并缓存

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

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

  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

[java] view plaincopy

  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

[java] view plaincopy

    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下载网络图片并缓存

时间: 2024-10-29 02:50:02

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

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

通过网络地址获取网络图片,点击下载将图片显示出来,然后点击图片将图片保存到本地. 首先需要在manifest上添加一些权限: [java] view plain copy <!-- 访问网络的权限 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 文件读取的权限 --> <uses-permission android:name="andro

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

使用Picasso组件去下载图片会发现图片宽高会变形不受等比缩放控制,即使设置了图片的 scaleType,可能是对Picasso的api没有用对, Picasso.with(this.activity) .load(AppModel.GetInstance().userAvatarPath) .noFade() .fit() .into(avatar) 使用Glide库会更加方便,很好控制下载好的图片宽高等比缩放 1,布局如下: <ImageView android:id="@+id/q

Android客户端中Bitmap的下载过程和缓存机制

加载流程: if(内存命中){ 从内存中读取 }else{ create AsyncTasks,task中的多个Runnable是通过堆栈先进后出的方式来调度,而非队列式的先进先出,目的是最先加载用户最近划到或打开的图片. } AsyncTask: //do in background——该后台进程在用户scroll列表的时候会暂停,从而减小了列表划动时cpu的overhead,此方法也被ImageLoader和facebook的官方app所使用. if(磁盘缓存命中){ 从缓存中读取 }els

Android之ListView异步加载网络图片(优化缓存机制)【转】

网上关于这个方面的文章也不少,基本的思路是线程+缓存来解决.下面提出一些优化: 1.采用线程池 2.内存缓存+文件缓存 3.内存缓存中网上很多是采用SoftReference来防止堆溢出,这儿严格限制只能使用最大JVM内存的1/4 4.对下载的图片进行按比例缩放,以减少内存的消耗 具体的代码里面说明.先放上内存缓存类的代码MemoryCache.java: public class MemoryCache { private static final String TAG = "MemoryCa

android 网络图片双缓存

本文转自:http://blog.csdn.net/a79412906/article/details/10180583 Android每次加载图片很浪费时间.所以设计了一个图片缓存技术来解决每次android手机加载图片的问题 内存的读取速度是最快的,然后是文件的读取速度,最后是网络资源的读取 既然内存的读取时间最快,我们好好利用内存资源.将内存再分两层缓存 强引用缓存不会轻易被回收,来保存常用数据,不常用的资源放入软引用缓存中. 对于硬引用和软引用的介绍: ⑴强引用(StrongRefere

打造支持apk下载和html5缓存的 IIS(配合一个超简单的android APP使用)具体解释

为什么要做这个看起来不靠谱的东西呢? 由于刚学android开发,还不能非常好的熟练控制android界面的编辑和操作,所以我的一个急着要的运用就改为html5版本号了,反正这个运用也是须要从server获取大量数据来展示在手机上面的,也就是说:必须联网,才干正常工作,于是想了一下,反正都要联网获取数据,为什么不直接用我相对熟悉一点的 html来做这个运用呢?省的花费不够用的时间去学习android界面的控制,于是就简单了:用蹩脚的手段做了一个android程序的启动欢迎界面,内页就是一个全屏的

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

在Android开发中我们经常有这样的需求,从服务器上下载xml或者JSON类型的数据,其中包括一些图片资源,本demo模拟了这个需求,从网络上加载XML资源,其中包括图片,我们要做的解析XML里面的数据,并且把图片缓存到本地一个cache目录里面,并且用一个自定义的Adapter去填充到LIstView,demo运行效果见下图: 通过这个demo,要学会有一下几点 1.怎么解析一个XML 2.demo中用到的缓存图片到本地一个临时目录的思想是怎样的? 3.AsyncTask类的使用,因为要去异

Android实战简易教程-第七十一枪(异步网络下载网络图片及图片廊制作)

首先来实现异步下载网络图片,布局文件如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_pare

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

原文:http://blog.csdn.net/java_jh/article/details/20068915 迟点出更新的.这个还有BUG.因为软引应不给力了.2.3之后 前几天的原文有一个线程管理与加载源过多,造成浪费流量的问题.下面对这进下改进的一些说明(红色为新加) 这两天一直在优化这个问题.google也很多种做法.但发现都是比较不全面. 比如: 一些只实现了异步加载,却没有线程池与软引用. 一些是用AsynTast的, 一些有了线程池但加载所有的图片,这样造成具大资源浪费 一些是用