但是我从来没有在我的代码中使用过WeakReference。如何使用WeakReference使我的应用程序更高效,特别是Android应用程序?
WeakReference
和在普通Java中使用它没有任何区别。每当您需要对对象进行引用,但不希望该引用保护对象免受垃圾回收器的影响时,应考虑使用它。一个经典的例子是高内存使用时要进行垃圾回收的缓存(通常使用WeakHashMap
实现)。也请务必查看SoftReference
和PhantomReference
。
编辑: Tom提出了关于使用WeakHashMap
实现缓存的一些担忧。这里有一篇文章说明了问题:WeakHashMap不是缓存!Tom是正确的,因为由于WeakHashMap
缓存而导致Netbeans性能不佳而发出了投诉。我仍然认为使用WeakHashMap
实现缓存,然后将其与使用SoftReference
手动实现的自定义缓存进行比较,这将是一个很好的学习经验。在真实世界中,您可能不会使用这两个解决方案之一,因为使用像Apache JCS这样的第三方库更有意义。WeakHashMap
作为缓存是致命的。条目可能会在创建后立即被删除。当你进行测试时,这可能不会发生,但在实际使用中很可能会发生。需要注意的是,这可能会导致NetBeans出现有效的100% CPU停止。 - Tom Hawtin - tacklineWeakHashMap
实现的。 - dbyrne[编辑2] 我找到了另一个很好的WeakReference
示例。高效显示位图培训指南中的在UI线程之外处理位图页面,展示了AsyncTask中WeakReference
的一种用法。
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private int data = 0;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
@Override
protected Bitmap doInBackground(Integer... params) {
data = params[0];
return decodeSampledBitmapFromResource(getResources(), data, 100, 100));
}
// Once complete, see if ImageView is still around and set bitmap.
@Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
愉快的编码!ImageView的WeakReference确保AsyncTask不会阻止ImageView及其引用的任何内容被垃圾回收。不能保证任务完成时ImageView仍然存在,因此您还必须在onPostExecute()中检查引用。如果用户在任务完成之前导航离开活动或发生配置更改,则可能不再存在ImageView。
[编辑] 我找到了一个非常好的WeakReference
示例,来自facebook-android-sdk。 ToolTipPopup类只是一个简单的小部件类,用于在锚点视图上方显示工具提示。我拍了一张截图。
WeakReference
类来持有对锚视图的引用是很有意义的,因为这使得即使提示框实例的生命周期比其锚视图长时,锚视图也可以被垃圾回收。
祝编程愉快!:)
让我分享一个使用WeakReference
类的工作示例。这是来自Android框架小部件AutoCompleteTextView
的一小段代码片段。
简而言之,WeakReference
类用于持有View
对象,以防止在此示例中发生内存泄漏。
我将复制并粘贴PopupDataSetObserver类,它是AutoCompleteTextView
的嵌套类。它非常简单,注释很好地解释了该类。祝你编程愉快! :)
/**
* Static inner listener that keeps a WeakReference to the actual AutoCompleteTextView.
* <p>
* This way, if adapter has a longer life span than the View, we won't leak the View, instead
* we will just leak a small Observer with 1 field.
*/
private static class PopupDataSetObserver extends DataSetObserver {
private final WeakReference<AutoCompleteTextView> mViewReference;
private PopupDataSetObserver(AutoCompleteTextView view) {
mViewReference = new WeakReference<AutoCompleteTextView>(view);
}
@Override
public void onChanged() {
final AutoCompleteTextView textView = mViewReference.get();
if (textView != null && textView.mAdapter != null) {
// If the popup is not showing already, showing it will cause
// the list of data set observers attached to the adapter to
// change. We can't do it from here, because we are in the middle
// of iterating through the list of observers.
textView.post(updateRunnable);
}
}
private final Runnable updateRunnable = new Runnable() {
@Override
public void run() {
final AutoCompleteTextView textView = mViewReference.get();
if (textView == null) {
return;
}
final ListAdapter adapter = textView.mAdapter;
if (adapter == null) {
return;
}
textView.updateDropDownForFilter(adapter.getCount());
}
};
}
而 PopupDataSetObserver
被用于设置适配器。
public <T extends ListAdapter & Filterable> void setAdapter(T adapter) {
if (mObserver == null) {
mObserver = new PopupDataSetObserver(this);
} else if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mObserver);
}
mAdapter = adapter;
if (mAdapter != null) {
//noinspection unchecked
mFilter = ((Filterable) mAdapter).getFilter();
adapter.registerDataSetObserver(mObserver);
} else {
mFilter = null;
}
mPopup.setAdapter(mAdapter);
}
最后一件事。我也想知道在Android应用程序中使用WeakReference
的工作示例,并且我可以在其官方示例应用程序中找到一些示例。但是,我确实无法理解其中一些的用法。例如,ThreadSample和DisplayingBitmaps应用程序在其代码中使用WeakReference
,但经过运行几个测试,我发现get()方法从未返回null
,因为引用的视图对象在适配器中被回收,而不是被垃圾回收。
其他一些答案似乎不完整或过长。这里是一个通用的答案。
您可以执行以下步骤:
WeakReference
变量MyClass
具有对 AnotherClass
的弱引用。
public class MyClass {
// 1. Create a WeakReference variable
private WeakReference<AnotherClass> mAnotherClassReference;
// 2. Set the weak reference (nothing special about the method name)
void setWeakReference(AnotherClass anotherClass) {
mAnotherClassReference = new WeakReference<>(anotherClass);
}
// 3. Use the weak reference
void doSomething() {
AnotherClass anotherClass = mAnotherClassReference.get();
if (anotherClass == null) return;
// do something with anotherClass
}
}
AnotherClass
对 MyClass
拥有强引用。
public class AnotherClass {
// strong reference
MyClass mMyClass;
// allow MyClass to get a weak reference to this class
void someMethod() {
mMyClass = new MyClass();
mMyClass.setWeakReference(this);
}
}
MyClass
是A,AnotherClass
是B。//允许 MyClass 获取对这个类的弱引用 void someMethod() { mMyClass = new MyClass(); mMyClass.someMethod(this); }
是什么意思? - likejudodoSomething
函数中调用 get
函数之前,需要检查 weakreference
对象本身是否为 null
。 - Behrouz.M“规范化”映射是指在内存中保留一个对象实例,而所有其他实例通过指针或类似的机制查找该特定实例。这就是弱引用可以发挥作用的地方。 简单来说,WeakReference对象可用于创建指向系统中对象的指针,同时允许垃圾回收器在它们超出范围后回收这些对象。例如,如果我有以下代码:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( object );
}
}
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( new WeakReference(object) );
}
}