• 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 }
    View Code


    最开始时我在自己的项目中也采取这样的代码段,从界面上来说没有发现什么问题,也还算流畅。可后来某次抓包分析数据的时候,在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 }
  • 相关阅读:
    JavaScript HTML DOM 事件监听器
    点击 和 松开鼠标 触发函数
    当鼠标移动过来 or 鼠标移开 触发函数
    onchange 事件(当焦点不在input框触发函数 )
    把2张表的数据合并成一张表
    Dome操作
    字典里面 值对应是函数的用法
    全局变量和局部变量的问题
    try catch finally 捕获异常的方法
    js 正则
  • 原文地址:https://www.cnblogs.com/xutao1988/p/3301912.html
Copyright © 2020-2023  润新知