【发布时间】:2011-09-25 20:32:18
【问题描述】:
我的申请中收到了OutOfMemoryError。当我浏览了一些教程时,我才知道,我可以使用Softreference/Weakreference 来解决这个问题。但是我不知道怎么用Softreference/Weakreference。
请向我推荐一些提供软引用或弱引用示例的教程。
谢谢...
【问题讨论】:
标签: android weak-references soft-references
我的申请中收到了OutOfMemoryError。当我浏览了一些教程时,我才知道,我可以使用Softreference/Weakreference 来解决这个问题。但是我不知道怎么用Softreference/Weakreference。
请向我推荐一些提供软引用或弱引用示例的教程。
谢谢...
【问题讨论】:
标签: android weak-references soft-references
要创建WeakReference,语法为WeakReference<SomeType> myWeakReference = new WeakReference<SomeType>(actualObject);。要通过 WeakReference 检索对象,请检查 if (weakWidget == null)。这样一来,如果 NullPointerException 已经被垃圾回收,您就可以避免它。
This Java.net article by Ethan Nicholas 解释了为什么你会想要使用WeakReference 而不是强的。它提供了一个名为Widget 的final(不可扩展)类的示例,该类没有定义串行UID,假设开发人员决定定义一个串行UID 来跟踪每个Widget 实例。他们通过创建一个新的HashMap 并执行类似serialNumberMap.put(widget, widgetSerialNumber); 之类的操作来实现这一点,这是一个强大的参考。这意味着它必须在不再需要时显式清理。开发人员负责准确了解何时手动“垃圾收集”该引用并将其从 HashMap 中删除,只有在他们真的确定不再需要它时才应该这样做。这可能是您在应用程序中遇到的问题。
在这种特殊情况下,正如文章所解释的那样,开发人员可以改用 WeakHashMap 类(正如 @NayAneshGupte 在他的示例中所说的那样),其中密钥实际上是 WeakReference。这将允许 JVM 在它认为合适的时候取消旧的 Widgets 的键,以便垃圾收集器可以出现并销毁它们的关联对象。
文章还继续讨论SoftReferences 和PhantomReferences(我从未使用过)。您可以在this javapapers.com article 和this Rally blog 中阅读有关所有这些的更多信息。
【讨论】:
package com.myapp;
import java.io.File;
import java.lang.ref.SoftReference;
import java.util.WeakHashMap;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
public class BitmapSoftRefrences {
public static String SDPATH = Environment.getExternalStorageDirectory()
+ "/MYAPP";
// 1. create a cache map
public static WeakHashMap<String, SoftReference<Bitmap>> mCache = new WeakHashMap<String, SoftReference<Bitmap>>();
public static String TAG = "BitmapSoftRefrences";
// 2. ask for bitmap
public static Bitmap get(String key) {
if (key == null) {
return null;
}
try {
if (mCache.containsKey(key)) {
SoftReference<Bitmap> reference = mCache.get(key);
Bitmap bitmap = reference.get();
if (bitmap != null) {
return bitmap;
}
return decodeFile(key);
}
} catch (Exception e) {
// TODO: handle exception
Logger.debug(BitmapSoftRefrences.class,
"EXCEPTION: " + e.getMessage());
}
// the key does not exists so it could be that the
// file is not downloaded or decoded yet...
File file = new File(SDPATH + "/" + key);
if (file.exists()) {
return decodeFile(key);
} else {
Logger.debug(BitmapSoftRefrences.class, "RuntimeException");
throw new RuntimeException("RuntimeException!");
}
}
// 3. the decode file will return bitmap if bitmap is not cached
public static Bitmap decodeFile(String key) {
// --- prevent scaling
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeFile(SDPATH + "/" + key, opt);
mCache.put(key, new SoftReference<Bitmap>(bitmap));
return bitmap;
}
public static void clear() {
mCache.clear();
}
}
【讨论】:
请看下面的教程
【讨论】: