Android 图片异步加载的体会,SoftReference已经不再适用
在网络上搜索Android图片异步加载的相关文章,目前大部分提到的解决方案,都是采用Map<String, SoftReference<Drawable>> 这样软引用的方式缓存网络图片。具体的例子见这篇文章。

1 public class AsyncImageLoader {
2
3 private HashMap<String, SoftReference<Drawable>> imageCache;
4
5 public AsyncImageLoader() {
6 imageCache = new HashMap<String, SoftReference<Drawable>>();
7 }
8
9 public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) {
10 if (imageCache.containsKey(imageUrl)) {
11 SoftReference<Drawable> softReference = imageCache.get(imageUrl);
12 Drawable drawable = softReference.get();
13 if (drawable != null) {
14 return drawable;
15 }
16 }
17 final Handler handler = new Handler() {
18 public void handleMessage(Message message) {
19 imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
20 }
21 };
22 new Thread() {
23 @Override
24 public void run() {
25 Drawable drawable = loadImageFromUrl(imageUrl);
26 imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
27 Message message = handler.obtainMessage(0, drawable);
28 handler.sendMessage(message);
29 }
30 }.start();
31 return null;
32 }
33
34 public static Drawable loadImageFromUrl(String url) {
35 URL m;
36 InputStream i = null;
37 try {
38 m = new URL(url);
39 i = (InputStream) m.getContent();
40 } catch (MalformedURLException e1) {
41 e1.printStackTrace();
42 } catch (IOException e) {
43 e.printStackTrace();
44 }
45 Drawable d = Drawable.createFromStream(i, "src");
46 return d;
47 }
48
49 public interface ImageCallback {
50 public void imageLoaded(Drawable imageDrawable, String imageUrl);
51 }
52
53 }

最开始时我在自己的项目中也采取这样的代码段,从界面上来说没有发现什么问题,也还算流畅。可后来某次抓包分析数据的时候,在ListView异步加载图片已经完全,我在上下滑动listview时,依旧会有网络请求发出不断加载图片,非常奇怪。从以上代码里可以看到,异步加载下来的图片全都存在了imageCache中,应该可以直接调用缓存中的图片来显示就可以了。
查找资料以后发现了其中的玄机,具体可见Android官方的这篇文章,Caching
Bitmaps。里面提到用 SoftReference 或者 WeakReference做图片缓存的方法在Android 2.3版本以后已经不被推荐了。因为内存对SoftReference和WeakReference的回收更加频繁,从而也导致了我在上面说的反复从网络上拉取图片的操作。
Android官方推荐最新的解决办法,是采用LruCache。如果图片数量巨大,也可以进一步考虑将图片缓存到sd卡中,可以采用DiskLruCache。具体的逻辑和上文其实差不多。相关代码如下:

1 private LruCache<String, Bitmap> mMemoryCache;
2
3 @Override
4 protected void onCreate(Bundle savedInstanceState) {
5 ...
6 // Get max available VM memory, exceeding this amount will throw an
7 // OutOfMemory exception. Stored in kilobytes as LruCache takes an
8 // int in its constructor.
9 final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
10
11 // Use 1/8th of the available memory for this memory cache.
12 final int cacheSize = maxMemory / 8;
13
14 mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
15 @Override
16 protected int sizeOf(String key, Bitmap bitmap) {
17 // The cache size will be measured in kilobytes rather than
18 // number of items.
19 return bitmap.getByteCount() / 1024;
20 }
21 };
22 ...
23 }
24
25 public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
26 if (getBitmapFromMemCache(key) == null) {
27 mMemoryCache.put(key, bitmap);
28 }
29 }
30
31 public Bitmap getBitmapFromMemCache(String key) {
32 return mMemoryCache.get(key);
33 }
Android 图片异步加载的体会,SoftReference已经不再适用的更多相关文章
- Android图片异步加载之Android-Universal-Image-Loader
将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...
- Android图片异步加载之Android-Universal-Image-Loader(转)
今天要介绍的是Github上一个使用非常广泛的图片异步加载库Android-Universal-Image-Loader,该项目的功能十分强大,可以说是我见过的目前功能最全.性能最优的图片异步加载解决 ...
- Android图片异步加载框架Android-Universal-Image-Loader
版权声明:本文为博主原创文章,未经博主允许不得转载. Android-Universal-Image-Loader是一个图片异步加载,缓存和显示的框架.这个框架已经被很多开发者所使用,是最常用的几个 ...
- [置顶] Android图片异步加载之Android-Universal-Image-Loader
将近一个月没有更新博客了,由于这段时间以来准备毕业论文等各种事务缠身,一直没有时间和精力沉下来继续学习和整理一些东西.最近刚刚恢复到正轨,正好这两天看了下Android上关于图片异步加载的开源项目,就 ...
- Android图片异步加载
原:http://www.cnblogs.com/angeldevil/archive/2012/09/16/2687174.html 相关:https://github.com/nostra13/A ...
- Android图片异步加载的方法
很多时候,我们在加载大图片或者需要处理较多图像数据的时候,希望显示效果能好点,不至于因为图片解码耗时产生ANR等情况,不得不说异步加载是个不错的方法.说到异步加载,避免application出现ANR ...
- Android 图片异步加载 加载网络图片
最近用到了加载网络图片,研究了一下,写一点简单的介绍: 首先创建一个线程去取图片(网络请求必须放在线程中): /** * 使用继承java.lang.Thread类的方式创建一个线程 * 直接取图片, ...
- Android ListView 图片异步加载和图片内存缓存
开发Android应用经常需要处理图片的加载问题.因为图片一般都是存放在服务器端,需要联网去加载,而这又是一个比较耗时的过程,所以Android中都是通过开启一个异步线程去加载.为了增加用户体验,给用 ...
- Android新浪微博客户端(七)——ListView中的图片异步加载、缓存
原文出自:方杰|http://fangjie.info/?p=193转载请注明出处 最终效果演示:http://fangjie.sinaapp.com/?page_id=54 该项目代码已经放到git ...
随机推荐
- shell 函数
1 shell函数的定义及其调用 shell函数有两种格式: function name { commands } name() { commands } 其中,name为函数名,commands为函 ...
- [转]Linux下的图形库介绍
[转]Linux 下的图形库介绍 http://blog.csdn.net/gogor/article/details/5925925 在进行Linux下的图形系统编程时,我们常常会遇到以下这些概念: ...
- 读Windows编程
1.Windows是一个消息驱动系统.它通过把消息投入应用程序消息队列中或者把消息发送给合适的窗口消息处理程序,将发生的各种事件通知给应用程序 2.尽管一个动态链接库模块可能有其它扩展名(如.EXE或 ...
- skill-如何禁止浏览器的默认行为
在默认情况下,点击链接,浏览器会向href所指的地址发送请求, 点击表单提交,浏览器会将表单中的数据进行发送 如果要禁止,可以使用如下语句:
- CString string char* char 之间的字符转换(多种方法)
在写程序的时候,我们经常遇到各种各样的类型转换,比如 char* CString string 之间的互相转换.首先解释下三者的含义. CString 是一种很有用的数据类型.它们很大程度上简化了MF ...
- python中fork()函数生成子进程分析
python的os module中有fork()函数用于生成子进程,生成的子进程是父进程的镜像,但是它们有各自的地址空间,子进程复制一份父进程内存给自己,两个进程之 间的执行是相互独立的,其执行顺序可 ...
- bzoj 2821 分块处理
大题思路就是分块,将n个数分成sqrt(n)个块,然后 处理出一个w数组,w[i,j]代表第i个块到第j个块的答案 那么对于每组询问l,r如果l,r在同一个块中,直接暴力做就行了 如果不在同一个块中, ...
- EditPlus配置[C++] [Python] [Java] 编译运行环境
以前一直用Codeblocks写C++,eclipse写Java,再在eclipse里面集成PyDev写Python,首先无法忍受代码自动补全功能(这个功能也许你万分喜欢),也无法忍受如此重量级的ID ...
- java中的匿名内部类
匿名内部类在java编码中不是很常见,它可一让类实现多继承的特性(多个父类~1个子类) java中的匿名内部类总结http://www.cnblogs.com/nerxious/archive/201 ...
- CoreText 使用教程
[iOS开发] CoreText 使用教程:以创建一个简单的杂志应用为例抢沙发 分类:iPhone开发 标签:CoreText.iOS.iOS开发.iOS开发教程.杂志应用 BBS.CHINAAPP. ...