我创建了一个ViewFlipper,用于在单一活动中显示Internet中的图像。投掷时,将图像设置为imageView,然后将其添加到viewflipper。 但问题是OOM总是在显示约20张图像后出现。 我做了一些干净的工作来解决它并且它不起作用! 这是代码。
public class ImageCache {
static private ImageCache cache;
private Hashtable<Integer, MySoftRef> hashRefs;
private ReferenceQueue<Bitmap> q;
private class MySoftRef extends SoftReference<Bitmap> {
private Integer _key = 0;
public MySoftRef(Bitmap bmp, ReferenceQueue<Bitmap> q, int key) {
super(bmp, q);
_key = key;
}
}
public ImageCache() {
hashRefs = new Hashtable<Integer, MySoftRef>();
q = new ReferenceQueue<Bitmap>();
}
public static ImageCache getInstance() {
if (cache == null) {
cache = new ImageCache();
}
return cache;
}
private void addCacheBitmap(Bitmap bmp, Integer key) {
cleanCache();
MySoftRef ref = new MySoftRef(bmp, q, key);
hashRefs.put(key, ref);
}
public Bitmap getBitmap(int resId) {
Bitmap bmp = null;
if (hashRefs.containsKey(resId)) {
MySoftRef ref = (MySoftRef) hashRefs.get(resId);
bmp = (Bitmap) ref.get();
}
if (bmp == null) {
URL imgUrl = null;
try {
imgUrl = new URL("http:/example/images/" + resId
+ ".jpg");
HttpURLConnection conn = (HttpURLConnection) imgUrl
.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
bmp = BitmapFactory.decodeStream(is);
is.close();
addCacheBitmap(bmp, resId);
} catch (Exception e) {
e.printStackTrace();
}
}
return bmp;
}
private void cleanCache() {
MySoftRef ref = null;
while ((ref = (MySoftRef) q.poll()) != null) {
hashRefs.remove(ref._key);
}
}
public void clearCache() {
cleanCache();
hashRefs.clear();
System.gc();
System.runFinalization();
}
这是loadimage代码。
public void LoadImage(int n){
iv = new ImageView(this);
imageCache = new ImageCache();
Bitmap bm = imageCache.getBitmap(n);
iv.setImageBitmap(bm);
iv.setScaleType(ImageView.ScaleType.CENTER);
viewFlipper.addView(iv, new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
}
答案 0 :(得分:0)
释放分配给Bitmap的内存的唯一方法是recycle()
。您应该removeView(View)
不在[current - 1; current + 1]
范围内,然后recycle
您自己分配的位图。所有这些代码对我来说似乎都太过分了,而且调用GC并不是一个好主意。您可以在Permanet存储上保存InputStream的内容,这样就不会有网络开销。
答案 1 :(得分:0)
您只应加载并保留所需的3张图像:
释放其他人的记忆。使用recycle()功能。
如果需要,您甚至可以保留5张图像。但是没有必要把它们全部保留下来。
如果您希望应用程序被激活,您可以将缩略图保留在内存中,显示它,如果您在图像上停留的时间超过x秒,则只加载完整图像。
以下是创建较小图片和管理位图列表的代码
Options mThumbOpts = new Options();
mThumbOpts.inSampleSize = 4;
/** The fonction to get a Bitmap from the list */
private Bitmap getBitmap(int id) {
// TODO recycle previous/next bitmaps here (id -2 and id +2 if they exist)
// Reload the image if necessary
if (bitmapList[id] == null || bitmapList[id].isRecycled()) {
bitmapList[id] = BitmapFactory.decodeFile(imagePath, mThumbOpts);
}
return bitmapList[id];
}
inSampleSize设置为值&gt; 1,请求解码器对原始图像进行二次采样,返回较小的图像以节省存储空间 使用2的幂可以提高效率。
答案 2 :(得分:0)
根据您的代码,您不使用ImageCache
类的单一性质,每次调用ImageCache
时都会创建新的LoadImage(int n)
实例:
imageCache = new ImageCache();
Bitmap bm = imageCache.getBitmap(n);
这真的很奇怪。改为使用:
imageCache = ImageCache.getInstance();