Android开发中图片的三级缓存策略

一、简介

现在的Android应用程序中,不可避免的都会使用到图片,如果每次加载图片的时候都要从网络重新拉取,这样不但很耗费用户的流量,而且图片加载的也会很慢,用户体验很不好。所以一个应用的图片缓存策略是很重要的。通常情况下,Android应用程序中图片的缓存策略采用“内存-本地-网络”三级缓存策略,首先应用程序访问网络拉取图片,分别将加载的图片保存在本地SD卡中和内存中,当程序再一次需要加载图片的时候,先判断内存中是否有缓存,有则直接从内存中拉取,否则查看本地SD卡中是否有缓存,SD卡中如果存在缓存,则图片从SD卡中拉取,否则从网络加载图片。依据这三级缓存机制,可以让我们的应用程序在加载图片的时候做到游刃有余,有效的避免内存溢出。

PS:当然现在处理网络图片的时候,一般人都会选择XUtils中的BitmapUtil,它已经将网络缓存处理的相当好了,使用起来非常方便--本人就一直在用。仿照BitMapUtil的实现思路,定制一个自己的图片加载工具,来理解一下三级缓存的策略,希望对自己会有一个提升。

二、网络缓存

网络拉取图片严格来讲不能称之为缓存,实质上就是下载url对应的图片,我们这里姑且把它看作是缓存的一种。仿照BitmapUtil中的display方法,我自己定制的CustomBitmapUtils也定义这个方法,根据传入的url,将图片设置到ivPic控件上。

[java] view
plain
 copy

  1. public void display(ImageView ivPic, String url) {
  2. }

定义网络缓存的工具类,在访问网络的时候,我使用了AsyncTask来实现,在AsyncTask的doInBackGround方法里下载图片,然后将 图片设置给ivPic控件,AsyncTask有三个泛型,其中第一个泛型是执行异步任务的时候,通过execute传过来的参数,第二个泛型是更新的进度,第三个泛型是异步任务执行完成之后,返回来的结果,我们这里返回一个Bitmap。具体的下载实现代码如下:

[java] view
plain
 copy

  1. <pre name="code" class="java">/**
  2. * 网络缓存的工具类
  3. *
  4. * @author ZHY
  5. *
  6. */
  7. public class NetCacheUtils {
  8. private LocalCacheUtils localCacheUtils;
  9. private MemoryCacheUtils memoryCacheUtils;
  10. public NetCacheUtils() {
  11. localCacheUtils = new LocalCacheUtils();
  12. memoryCacheUtils = new MemoryCacheUtils();
  13. }
  14. /**
  15. * 从网络下载图片
  16. *
  17. * @param ivPic
  18. * @param url
  19. */
  20. public void getBitmapFromNet(ImageView ivPic, String url) {
  21. // 访问网络的操作一定要在子线程中进行,采用异步任务实现
  22. MyAsyncTask task = new MyAsyncTask();
  23. task.execute(ivPic, url);
  24. }
  25. /**
  26. * 第一个泛型--异步任务执行的时候,通过execute传过来的参数; 第二个泛型--更新进度; 第三个泛型--异步任务执行以后返回的结果
  27. *
  28. * @author ZHY
  29. *
  30. */
  31. private class MyAsyncTask extends AsyncTask<Object, Void, Bitmap> {
  32. private ImageView ivPic;
  33. private String url;
  34. // 耗时任务执行之前 --主线程
  35. @Override
  36. protected void onPreExecute() {
  37. super.onPreExecute();
  38. }
  39. // 后台执行的任务
  40. @Override
  41. protected Bitmap doInBackground(Object... params) {
  42. // 执行异步任务的时候,将URL传过来
  43. ivPic = (ImageView) params[0];
  44. url = (String) params[1];
  45. Bitmap bitmap = downloadBitmap(url);
  46. // 为了保证ImageView控件和URL一一对应,给ImageView设定一个标记
  47. ivPic.setTag(url);// 关联ivPic和URL
  48. return bitmap;
  49. }
  50. // 更新进度 --主线程
  51. @Override
  52. protected void onProgressUpdate(Void... values) {
  53. super.onProgressUpdate(values);
  54. }
  55. // 耗时任务执行之后--主线程
  56. @Override
  57. protected void onPostExecute(Bitmap result) {
  58. String mCurrentUrl = (String) ivPic.getTag();
  59. if (url.equals(mCurrentUrl)) {
  60. ivPic.setImageBitmap(result);
  61. System.out.println("从网络获取图片");
  62. // 从网络加载完之后,将图片保存到本地SD卡一份,保存到内存中一份
  63. localCacheUtils.setBitmap2Local(url, result);
  64. // 从网络加载完之后,将图片保存到本地SD卡一份,保存到内存中一份
  65. memoryCacheUtils.setBitmap2Memory(url, result);
  66. }
  67. }
  68. }
  69. /**
  70. * 下载网络图片
  71. *
  72. * @param url
  73. * @return
  74. */
  75. private Bitmap downloadBitmap(String url) {
  76. HttpURLConnection conn = null;
  77. try {
  78. URL mURL = new URL(url);
  79. // 打开HttpURLConnection连接
  80. conn = (HttpURLConnection) mURL.openConnection();
  81. // 设置参数
  82. conn.setConnectTimeout(5000);
  83. conn.setReadTimeout(5000);
  84. conn.setRequestMethod("GET");
  85. // 开启连接
  86. conn.connect();
  87. // 获得响应码
  88. int code = conn.getResponseCode();
  89. if (code == 200) {
  90. // 相应成功,获得网络返回来的输入流
  91. InputStream is = conn.getInputStream();
  92. // 图片的输入流获取成功之后,设置图片的压缩参数,将图片进行压缩
  93. BitmapFactory.Options options = new BitmapFactory.Options();
  94. options.inSampleSize = 2;// 将图片的宽高都压缩为原来的一半,在开发中此参数需要根据图片展示的大小来确定,否则可能展示的不正常
  95. options.inPreferredConfig = Bitmap.Config.RGB_565;// 这个压缩的最小
  96. // Bitmap bitmap = BitmapFactory.decodeStream(is);
  97. Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);// 经过压缩的图片
  98. return bitmap;
  99. }
  100. } catch (Exception e) {
  101. e.printStackTrace();
  102. } finally {
  103. // 断开连接
  104. conn.disconnect();
  105. }
  106. return null;
  107. }
  108. }

[java] view
plain
 copy

  1. </pre><p></p><pre>

三、本地缓存

从网络加载完图片之后,将图片保存到本地SD卡中。在加载图片的时候,判断一下SD卡中是否有图片缓存,如果有,就直接从SD卡加载图片。本地缓存的工具类中有两个公共的方法,分别是向本地SD卡设置网络图片,获取SD卡中的图片。设置图片的时候采用键值对的形式进行存储,将图片的url作为键,作为文件的名字,图片的Bitmap作位值来保存。由于url含有特殊字符,不能直接作为图片的名字来存储,故采用url的MD5值作为文件的名字。

[java] view
plain
 copy

  1. /**
  2. * 本地缓存
  3. *
  4. * @author ZHY
  5. *
  6. */
  7. public class LocalCacheUtils {
  8. /**
  9. * 文件保存的路径
  10. */
  11. public static final String FILE_PATH = Environment
  12. .getExternalStorageDirectory().getAbsolutePath() + "/cache/pics";
  13. /**
  14. * 从本地SD卡获取网络图片,key是url的MD5值
  15. *
  16. * @param url
  17. * @return
  18. */
  19. public Bitmap getBitmapFromLocal(String url) {
  20. try {
  21. String fileName = MD5Encoder.encode(url);
  22. File file = new File(FILE_PATH, fileName);
  23. if (file.exists()) {
  24. Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(
  25. file));
  26. return bitmap;
  27. }
  28. } catch (Exception e) {
  29. e.printStackTrace();
  30. }
  31. return null;
  32. }
  33. /**
  34. * 向本地SD卡写网络图片
  35. *
  36. * @param url
  37. * @param bitmap
  38. */
  39. public void setBitmap2Local(String url, Bitmap bitmap) {
  40. try {
  41. // 文件的名字
  42. String fileName = MD5Encoder.encode(url);
  43. // 创建文件流,指向该路径,文件名叫做fileName
  44. File file = new File(FILE_PATH, fileName);
  45. // file其实是图片,它的父级File是文件夹,判断一下文件夹是否存在,如果不存在,创建文件夹
  46. File fileParent = file.getParentFile();
  47. if (!fileParent.exists()) {
  48. // 文件夹不存在
  49. fileParent.mkdirs();// 创建文件夹
  50. }
  51. // 将图片保存到本地
  52. bitmap.compress(CompressFormat.JPEG, 100,
  53. new FileOutputStream(file));
  54. } catch (Exception e) {
  55. e.printStackTrace();
  56. }
  57. }
  58. }

四、内存缓存

内存缓存说白了就是在内存中保存一份图片集合,首先会想到HashMap这种键值对的形式来进行保存,以url作为key,bitmap作为value。但是在Java中这种默认的new对象的方式是强引用,JVM在进行垃圾回收的时候是不会回收强引用的,所以如果加载的图片过多的话,map会越来越大,很容易出现OOM异常。在Android2.3之前,还可以通过软引用或者弱引用来解决,但是Android2.3之后,Google官方便不再推荐软引用了,Google推荐我们使用LruCache。

在过去,我们经常会使用一种非常流行的内存缓存技术的实现,即软引用或弱引用 (SoftReference or WeakReference)。但是现在已经不再推荐使用这种方式了,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。另外,Android 3.0 (API Level 11)中,图片的数据会存储在本地的内存当中,因而无法用一种可预见的方式将其释放,这就有潜在的风险造成应用程序的内存溢出并崩溃。

为了能够选择一个合适的缓存大小给LruCache, 有以下多个因素应该放入考虑范围内,例如:

  • 你的设备可以为每个应用程序分配多大的内存?Android默认是16M。
  • 设备屏幕上一次最多能显示多少张图片?有多少图片需要进行预加载,因为有可能很快也会显示在屏幕上?
  • 你的设备的屏幕大小和分辨率分别是多少?一个超高分辨率的设备(例如 Galaxy Nexus) 比起一个较低分辨率的设备(例如 Nexus S),在持有相同数量图片的时候,需要更大的缓存空间。
  • 图片的尺寸和大小,还有每张图片会占据多少内存空间。
  • 图片被访问的频率有多高?会不会有一些图片的访问频率比其它图片要高?如果有的话,你也许应该让一些图片常驻在内存当中,或者使用多个LruCache 对象来区分不同组的图片。
  • 你能维持好数量和质量之间的平衡吗?有些时候,存储多个低像素的图片,而在后台去开线程加载高像素的图片会更加的有效。

以上是Google对LruCache的描述,其实LruCache的使用非常简单,跟Map非常相近,只是在创建LruCache对象的时候需要指定它的最大允许内存,一般设置为当前应用程序的最大运行内存的八分之一即可。

[java] view
plain
 copy

  1. /**
  2. * 内存缓存
  3. *
  4. * @author ZHY
  5. *
  6. */
  7. public class MemoryCacheUtils {
  8. /*
  9. * 由于map默认是强引用,所有在JVM进行垃圾回收的时候不会回收map的引用
  10. */
  11. // private HashMap<String, Bitmap> map = new HashMap<String, Bitmap>();
  12. // 软引用的实例,在内存不够时,垃圾回收器会优先考虑回收
  13. // private HashMap<String, SoftReference<Bitmap>> mSoftReferenceMap = new
  14. // HashMap<String, SoftReference<Bitmap>>();
  15. // LruCache
  16. private LruCache<String, Bitmap> lruCache;
  17. public MemoryCacheUtils() {
  18. // lruCache最大允许内存一般为Android系统分给每个应用程序内存大小(默认Android系统给每个应用程序分配16兆内存)的八分之一(推荐)
  19. // 获得当前应用程序运行的内存大小
  20. long mCurrentMemory = Runtime.getRuntime().maxMemory();
  21. int maxSize = (int) (mCurrentMemory / 8);
  22. // 给LruCache设置最大的内存
  23. lruCache = new LruCache<String, Bitmap>(maxSize) {
  24. @Override
  25. protected int sizeOf(String key, Bitmap value) {
  26. // 获取每张图片所占内存的大小
  27. // 计算方法是:图片显示的宽度的像素点乘以高度的像素点
  28. int byteCount = value.getRowBytes() * value.getHeight();// 获取图片占用内存大小
  29. return byteCount;
  30. }
  31. };
  32. }
  33. /**
  34. * 从内存中读取Bitmap
  35. *
  36. * @param url
  37. * @return
  38. */
  39. public Bitmap getBitmapFromMemory(String url) {
  40. // Bitmap bitmap = map.get(url);
  41. // SoftReference<Bitmap> softReference = mSoftReferenceMap.get(url);
  42. // Bitmap bitmap = softReference.get();
  43. // 软引用在Android2.3以后就不推荐使用了,Google推荐使用lruCache
  44. // LRU--least recently use
  45. // 最近最少使用,将内存控制在一定的大小内,超过这个内存大小,就会优先释放最近最少使用的那些东东
  46. Bitmap bitmap = lruCache.get(url);
  47. return bitmap;
  48. }
  49. /**
  50. * 将图片保存到内存中
  51. *
  52. * @param url
  53. * @param bitmap
  54. */
  55. public void setBitmap2Memory(String url, Bitmap bitmap) {
  56. // 向内存中设置,key,value的形式,首先想到HashMap
  57. // map.put(url, bitmap);
  58. // 保存软引用到map中
  59. // SoftReference<Bitmap> mSoftReference = new
  60. // SoftReference<Bitmap>(bitmap);
  61. // mSoftReferenceMap.put(url, mSoftReference);
  62. lruCache.put(url, bitmap);
  63. }
  64. }

好了。现在三级缓存策略封装完毕,接下来定制我们自己的BitmapUtils

[java] view
plain
 copy

  1. /**
  2. * 自定义的加载图片的工具类,类似于Xutils中的BitmapUtil,在实际使用中,一般使用BitmapUtil,为了理解三级缓存,
  3. * 这里模拟BitmapUtil自定义了CustomBitmapUtil
  4. *
  5. * @author ZHY
  6. *
  7. */
  8. public class CustomBitmapUtils {
  9. private Bitmap bitmap;
  10. private NetCacheUtils netCacheUtils;
  11. private LocalCacheUtils localCacheUtils;
  12. private MemoryCacheUtils memoryCacheUtils;
  13. public CustomBitmapUtils() {
  14. netCacheUtils = new NetCacheUtils();
  15. localCacheUtils = new LocalCacheUtils();
  16. memoryCacheUtils = new MemoryCacheUtils();
  17. }
  18. /**
  19. * 加载图片,将当前URL对应的图片显示到ivPic的控件上
  20. *
  21. * @param ivPic
  22. *            ImageView控件
  23. * @param url
  24. *            图片的地址
  25. */
  26. public void display(ImageView ivPic, String url) {
  27. // 设置默认显示的图片
  28. ivPic.setImageResource(R.drawable.ic_launcher);
  29. // 1、内存缓存
  30. bitmap = memoryCacheUtils.getBitmapFromMemory(url);
  31. if (bitmap != null) {
  32. ivPic.setImageBitmap(bitmap);
  33. System.out.println("从内存缓存中加载图片");
  34. return;
  35. }
  36. // 2、本地磁盘缓存
  37. bitmap = localCacheUtils.getBitmapFromLocal(url);
  38. if (bitmap != null) {
  39. ivPic.setImageBitmap(bitmap);
  40. System.out.println("从本地SD卡加载的图片");
  41. memoryCacheUtils.setBitmap2Memory(url, bitmap);// 将图片保存到内存
  42. return;
  43. }
  44. // 3、网络缓存
  45. netCacheUtils.getBitmapFromNet(ivPic, url);
  46. /*
  47. * 从网络获取图片之后,将图片保存到手机SD卡中,在进行图片展示的时候,优先从SD卡中读取缓存,key是图片的URL的MD5值,
  48. * value是保存的图片bitmap
  49. */
  50. }
  51. }

在mainActivity中使用ListView加载网络图片

[java] view
plain
 copy

  1. /**
  2. * Android中三级缓存--网络缓存-本地缓存-内存缓存
  3. *
  4. * @author ZHY
  5. *
  6. */
  7. public class MainActivity extends Activity {
  8. private ListView list;
  9. private Button btn;
  10. private CustomBitmapUtils utils;
  11. private static final String BASE_URL = "http://192.168.0.148:8080/pics";
  12. // 初始化一些网络图片
  13. String[] urls = { BASE_URL + "/1.jpg", BASE_URL + "/2.jpg",
  14. BASE_URL + "/3.jpg", BASE_URL + "/4.jpg", BASE_URL + "/5.jpg",
  15. BASE_URL + "/6.jpg", BASE_URL + "/7.jpg", BASE_URL + "/8.jpg",
  16. BASE_URL + "/9.jpg", BASE_URL + "/10.jpg", BASE_URL + "/11.jpg",
  17. BASE_URL + "/12.jpg", BASE_URL + "/13.jpg", BASE_URL + "/14.jpg",
  18. BASE_URL + "/15.jpg", BASE_URL + "/16.jpg", BASE_URL + "/17.jpg",
  19. BASE_URL + "/18.jpg", BASE_URL + "/19.jpg", BASE_URL + "/20.jpg",
  20. BASE_URL + "/21.jpg", BASE_URL + "/22.jpg", BASE_URL + "/23.jpg",
  21. BASE_URL + "/24.jpg", BASE_URL + "/25.jpg", BASE_URL + "/26.jpg",
  22. BASE_URL + "/27.jpg", BASE_URL + "/28.jpg", BASE_URL + "/29.jpg",
  23. BASE_URL + "/30.jpg" };
  24. @Override
  25. protected void onCreate(Bundle savedInstanceState) {
  26. super.onCreate(savedInstanceState);
  27. setContentView(R.layout.activity_main);
  28. list = (ListView) findViewById(R.id.list);
  29. btn = (Button) findViewById(R.id.btn_load);
  30. utils = new CustomBitmapUtils();
  31. // 加载网络图片
  32. btn.setOnClickListener(new OnClickListener() {
  33. @Override
  34. public void onClick(View v) {
  35. MyAdapter adapter = new MyAdapter();
  36. list.setAdapter(adapter);
  37. }
  38. });
  39. }
  40. class MyAdapter extends BaseAdapter {
  41. @Override
  42. public int getCount() {
  43. return urls.length;
  44. }
  45. @Override
  46. public String getItem(int position) {
  47. return urls[position];
  48. }
  49. @Override
  50. public long getItemId(int position) {
  51. return position;
  52. }
  53. @Override
  54. public View getView(int position, View convertView, ViewGroup parent) {
  55. ViewHolder holder;
  56. if (convertView == null) {
  57. convertView = View.inflate(MainActivity.this,
  58. R.layout.item_list, null);
  59. holder = new ViewHolder();
  60. holder.ivPic = (ImageView) convertView.findViewById(R.id.iv);
  61. convertView.setTag(holder);
  62. } else {
  63. holder = (ViewHolder) convertView.getTag();
  64. }
  65. utils.display(holder.ivPic, urls[position]);
  66. return convertView;
  67. }
  68. class ViewHolder {
  69. ImageView ivPic;
  70. }
  71. }
  72. }

运行的结果如下:

程序第一次运行,日志打印如下

之后将图片缓存在SD卡中,从本地加载图片

然后将图片缓存到内存,从内存加载图片

OK,到目前为止,Android中图片的三级缓存原理就都介绍完了,我自己本人受益匪浅,希望能够帮助到需要的朋友。

时间: 2024-10-10 23:44:46

Android开发中图片的三级缓存策略的相关文章

Android中图片的三级缓存策略

一.简介 现在的Android应用程序中,不可避免的都会使用到图片,如果每次加载图片的时候都要从网络重新拉取,这样不但很耗费用户的流量,而且图片加载的也会很慢,用户体验很不好.所以一个应用的图片缓存策略是很重要的.通常情况下,Android应用程序中图片的缓存策略采用"内存-本地-网络"三级缓存策略,首先应用程序访问网络拉取图片,分别将加载的图片保存在本地SD卡中和内存中,当程序再一次需要加载图片的时候,先判断内存中是否有缓存,有则直接从内存中拉取,否则查看本地SD卡中是否有缓存,SD

android开发中图片优化步骤

android开发中图片优化方法 1.图片加载方法,方便用户加载图片 /*** * 加载本地图片 * @param context:主运行函数实例 * @param bitAdress:图片地址,一般指向R下的drawable目录 * @return */ public final Bitmap CreatImage(Context context, int bitAdress) { Bitmap bitmaptemp = null; bitmaptemp = BitmapFactory.dec

android中图片的三级缓存cache策略(内存/文件/网络)

实现图片缓存也不难,需要有相应的cache策略.这里我采用 内存-文件-网络 三层cache机制,其中内存缓存包括强引用缓存和软引用缓存(SoftReference),其实网络不算cache,这里姑且也把它划到缓存的层次结构中 1.简介 现在android应用中不可避免的要使用图片,有些图片是可以变化的,需要每次启动时从网络拉取,这种场景在有广告位的应用以及纯图片应用(比如百度美拍)中比较多. 现在有一个问题:假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量.在当前的状况下,对于非wi

简单地Android中图片的三级缓存机制

我们不能每次加载图片的时候都让用户从网络上下载,这样不仅浪费流量又会影响用户体验,所以Android中引入了图片的缓存这一操作机制. 原理: 首先根据图片的网络地址在网络上下载图片,将图片先缓存到内存缓存中,缓存到强引用中 也就是LruCache中.如果强引用中空间不足,就会将较早存储的图片对象驱逐到软引用(softReference)中存储,然后将图片缓存到文件(内部存储外部存储)中:读取图片的时候,先读取内存缓存,判断强引用中是否存在图片,如果强引用中存在,则直接读取,如果强引用中不存在,则

Android 开发中图片灰阶(黑白)显示

阅读本文之前关于将RGB颜色值转换为灰阶值的计算方法可参见: 三种算法转换彩色灰阶 http://aiilive.blog.51cto.com/1925756/1718960 灰阶显示图片的典型应用就是用户头像,如用户在线头像显示彩色(原图),不在线显示灰色(黑白图).总结一点就是更加一张原始图片来通过颜色的过滤处理计算得到不同显示效果的图片.这方法的API主要位于:android. 使用上文中提到的"三种算法转换彩色灰阶"一文中提到的灰阶计算方法产生的黑白图片显示效果如下图: 说明:

Android开发中使用七牛云存储进行图片上传下载

Android开发中的图片存储本来就是比较耗时耗地的事情,而使用第三方的七牛云,便可以很好的解决这些后顾之忧,最近我也是在学习七牛的SDK,将使用过程在这记录下来,方便以后使用. 先说一下七牛云的存储原理,上面这幅图片是官方给出的原理图,表述当然比较清晰了.可以看出,要进行图片上传的话可以分为五大步: 1. 客户端用户登录到APP的账号系统里面: 2. 客户端上传文件之前,需要向业务服务器申请七牛的上传凭证,这个凭证由业务服务器使用七牛提供的服务端SDK生成: 3. 客户端使用七牛提供的客户端S

Android开发中无处不在的设计模式——策略模式

这个系列停更了好久了,差不多可以重新拿起来更一篇了,这篇文章主要介绍策略模式.在这之前,先温习一下前面介绍的4种模式. 设计模式很重要! 设计模式很重要! 设计模式很重要! 重要的事说三遍!!! Android开发中无处不在的设计模式--单例模式 Android开发中无处不在的设计模式--Builder模式 Android开发中无处不在的设计模式--观察者模式 Android开发中无处不在的设计模式--原型模式 接着看下策略模式的定义 策略模式定义了一些列的算法,并将每一个算法封装起来,而且使它

Android开发中尽量避免使用jpg图片

由于jpg容易失真,所以在Android开发中尽量避免使用.jpg图片,而应该使用.png图片,它采用了从LZ77派生的无损数据压缩算法. 其实关于这点,Google已经暗示我们了: 发现了没有,在res下这些icon用的都是png格式.就是说Google推荐使用的是png格式的图片. 写到这,想起个小事,童鞋问:在命名一个Activity对应的布局文件的时候,怎么样算规范一些. 其实我们在新建一个Activity的时候,也可以在看到一些端倪: 如果你建立一个MainActivity那么默认的它

Android 开发中下载的图片 图库中看不到

Android 开发中下载的图片,但是代开图库的时候,不能马上看到图片.是因为android 内部有一个 扫描机制, 你下载之后图片已经存在了,但是没有被扫描到.所以你马上打开图库 看不到 下载的图片: 需啊哟加入下面的 代码 下载完成的hanlder 中处理: 直接调用就可以 MediaScannerConnection.scanFile( ShowBigImage.this, new String[] {url}, null, null);