viewpage listview gridview加载本地大图多图OOM处理办法

很少上博客园写东西了.

最近在写公司项目,由于需要加载本地相册通过viewpager方式来加载,

最后发现直接进入界面就OOM了.

经过几天的整理最终搞定.

现在将加载本地和加载网络图片的缓存工具类贴出代码.

需要用的直接调用其中的暴露出的方法,传入本地图片地址或网络图片地址 +imageview即可

代码如有问题请及时跟帖或者加QQ30338970交流.

  1 package cn.haodehaode.utils;
  2 
  3 import android.graphics.Bitmap;
  4 import android.graphics.BitmapFactory;
  5 import android.os.AsyncTask;
  6 import android.support.v4.util.LruCache;
  7 import android.widget.ImageView;
  8 
  9 import java.net.HttpURLConnection;
 10 import java.net.URL;
 11 import java.util.HashSet;
 12 import java.util.Set;
 13 
 14 import cn.haodehaode.R;
 15 
 16 /**
 17  * 图片缓存
 18  * 异步加载网络图片
 19  *
 20  * @author JALEN  c9n9m@163.com
 21  * @version V1.0
 22  * @Title: ${FILE_NAME}
 23  * @Package cn.haodehaode.utils
 24  * @Description: ${todo}
 25  * @date 15/10/29 13:39
 26  */
 27 public class LruCacheImgUrlUtils {
 28 
 29     private static LruCache<String, Bitmap> mMemoryCache;
 30 
 31     private static LruCacheImgUrlUtils lruCacheSingleton;
 32 
 33 
 34     /**
 35      * 记录所有正在下载或等待下载的任务。
 36      */
 37     private static Set<BitmapWorkerTasks> taskCollection;
 38 
 39     public static synchronized LruCacheImgUrlUtils getLruUrlCacheSingleton() {
 40         if (lruCacheSingleton == null) {
 41             lruCacheSingleton = new LruCacheImgUrlUtils();
 42 
 43             taskCollection = new HashSet<BitmapWorkerTasks>();
 44             // LruCache通过构造函数传入缓存值,以KB为单位。
 45             int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
 46             // 使用最大可用内存值的1/8作为缓存的大小。
 47             int cacheSize = maxMemory / 8;
 48             mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
 49                 @Override
 50                 protected int sizeOf(String key, Bitmap bitmap) {
 51                     // 重写此方法来衡量每张图片的大小,默认返回图片数量。
 52                     return bitmap.getByteCount() / 1024;
 53                 }
 54             };
 55         }
 56         return lruCacheSingleton;
 57     }
 58 
 59 
 60     /**
 61      * 将一张图片存储到LruCache中。
 62      *
 63      * @param key    LruCache的键,这里传入图片的URL地址。
 64      * @param bitmap LruCache的键,这里传入从网络上下载的Bitmap对象。
 65      */
 66     public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
 67         if (getBitmapFromMemoryCache(key) == null) {
 68             mMemoryCache.put(key, bitmap);
 69         }
 70     }
 71 
 72     /**
 73      * 从LruCache中获取一张图片,如果不存在就返回null。
 74      *
 75      * @param key LruCache的键,这里传入图片的URL地址。
 76      * @return 对应传入键的Bitmap对象,或者null。
 77      */
 78     public Bitmap getBitmapFromMemoryCache(String key) {
 79         return mMemoryCache.get(key);
 80     }
 81 
 82 
 83     /**
 84      * 给ImageView设置图片。首先从LruCache中取出图片的缓存,设置到ImageView上。如果LruCache中没有该图片的缓存,
 85      * 就给ImageView设置一张默认图片。
 86      *
 87      * @param imageUrl  图片的URL地址,用于作为LruCache的键。
 88      * @param imageView 用于显示图片的控件。
 89      */
 90     public void setImageView(String imageUrl, ImageView imageView) {
 91         Bitmap bitmap = getBitmapFromMemoryCache(imageUrl);
 92         if (bitmap != null) {
 93             imageView.setImageBitmap(bitmap);
 94         } else {
 95             imageView.setImageResource(R.drawable.empty_photo);
 96             BitmapWorkerTasks task = new BitmapWorkerTasks(imageView);
 97             task.execute(imageUrl);
 98         }
 99     }
100 
101 
102     /**
103      * 异步下载图片的任务。
104      *
105      * @author guolin
106      */
107     class BitmapWorkerTasks extends AsyncTask<String, Void, Bitmap> {
108 
109         private ImageView mImageView;
110 
111         public BitmapWorkerTasks(ImageView imageView) {
112             mImageView = imageView;
113         }
114 
115         /**
116          * 图片的URL地址
117          */
118         private String imageUrl;
119 
120         @Override
121         protected Bitmap doInBackground(String... params) {
122             imageUrl = params[0];
123             // 在后台开始下载图片
124             Bitmap bitmap = downloadBitmap(params[0]);
125             if (bitmap != null) {
126                 // 图片下载完成后缓存到LrcCache中
127                 addBitmapToMemoryCache(params[0], bitmap);
128             }
129             return bitmap;
130         }
131 
132         @Override
133         protected void onPostExecute(Bitmap bitmap) {
134             super.onPostExecute(bitmap);
135             // 根据Tag找到相应的ImageView控件,将下载好的图片显示出来。
136             if (mImageView != null && bitmap != null) {
137                 mImageView.setImageBitmap(bitmap);
138             }
139             taskCollection.remove(this);
140         }
141 
142         /**
143          * 建立HTTP请求,并获取Bitmap对象。
144          *
145          * @param imageUrl 图片的URL地址
146          * @return 解析后的Bitmap对象
147          */
148         private Bitmap downloadBitmap(String imageUrl) {
149             Bitmap bitmap = null;
150             HttpURLConnection con = null;
151             try {
152                 URL url = new URL(imageUrl);
153                 con = (HttpURLConnection) url.openConnection();
154                 con.setConnectTimeout(5 * 1000);
155                 con.setReadTimeout(10 * 1000);
156                 bitmap = BitmapFactory.decodeStream(con.getInputStream());
157             } catch (Exception e) {
158                 e.printStackTrace();
159             } finally {
160                 if (con != null) {
161                     con.disconnect();
162                 }
163             }
164             return bitmap;
165         }
166 
167     }
168 
169 
170 }
package cn.haodehaode.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.widget.ImageView;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;

import cn.haodehaode.R;

/**
 * 图片缓存
 *
 * @author JALEN  c9n9m@163.com
 * @version V1.0
 * @Title: ${FILE_NAME}
 * @Package cn.haodehaode.utils
 * @Description: ${todo}
 * @date 15/10/29 13:39
 */
public class LruCacheImgUtils {

    private static LruCache<String, Bitmap> mMemoryCache;

    private static LruCacheImgUtils lruCacheSingleton;


    public static synchronized LruCacheImgUtils getLruCacheSingleton() {
        if (lruCacheSingleton == null) {
            lruCacheSingleton = new LruCacheImgUtils();

            // LruCache通过构造函数传入缓存值,以KB为单位。
            int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
            // 使用最大可用内存值的1/8作为缓存的大小。
            int cacheSize = maxMemory / 8;
            mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
                @Override
                protected int sizeOf(String key, Bitmap bitmap) {
                    // 重写此方法来衡量每张图片的大小,默认返回图片数量。
                    return bitmap.getByteCount() / 1024;
                }
            };
        }
        return lruCacheSingleton;
    }

    public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
        if (getBitmapFromMemCache(key) == null) {
            mMemoryCache.put(key, bitmap);
        }
    }

    public Bitmap getBitmapFromMemCache(String key) {
        return mMemoryCache.get(key);
    }


    public void loadBitmap(String path, ImageView imageView) {
        final Bitmap bitmap = getBitmapFromMemCache(path);
        if (bitmap != null) {
            imageView.setImageBitmap(bitmap);
        } else {
            imageView.setImageResource(R.drawable.default_image);
            BitmapWorkerTask task = new BitmapWorkerTask(imageView);
            task.execute(path);
        }
    }


    public Bitmap decodeSampledBitmapFromResource(String path,
                                                  int reqWidth, int reqHeight) {
        // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);
        // 调用上面定义的方法计算inSampleSize值
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        // 使用获取到的inSampleSize值再次解析图片
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(path, options);
    }

    public static int calculateInSampleSize(BitmapFactory.Options options,
                                            int reqWidth, int reqHeight) {
        // 源图片的高度和宽度
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            // 计算出实际宽高和目标宽高的比率
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
            // 一定都会大于等于目标的宽和高。
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }


    class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {

        private ImageView mImageView;

        public BitmapWorkerTask(ImageView imageView) {
            mImageView = imageView;
        }

        // 在后台加载图片。
        @Override
        protected Bitmap doInBackground(String... params) {
            final Bitmap bitmap = decodeSampledBitmapFromResource(
                    params[0], 320, 320);
            addBitmapToMemoryCache(String.valueOf(params[0]), bitmap);
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            mImageView.setImageBitmap(bitmap);
        }
    }
}
原文地址:https://www.cnblogs.com/china-soft/p/4921010.html