Java和Android开发中如何使用WeakReference?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3243215/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use WeakReference in Java and Android development?
提问by Chris
I have been a java developer for 2 years.
我已经做了 2 年的 Java 开发人员。
But I have never wrote a WeakReference in my code. How to use WeakReference to make my application more efficient especially the Android application?
但是我从来没有在我的代码中写过 WeakReference。如何使用 WeakReference 使我的应用程序更高效,尤其是 Android 应用程序?
回答by dbyrne
Using a WeakReference
in Android isn't any different than using one in plain old Java. Here is a great guide which gives a detailed explanation: Understanding Weak References.
WeakReference
在 Android 中使用 a与在普通旧 Java 中使用 a没有任何不同。这是一个很好的指南,它给出了详细的解释:Understanding Weak References。
You should think about using one whenever you need a reference to an object, but you don't want that reference to protect the object from the garbage collector. A classic example is a cache that you want to be garbage collected when memory usage gets too high (often implemented with WeakHashMap
).
当您需要对对象的引用时,您应该考虑使用一个,但您不希望该引用保护对象免受垃圾收集器的影响。一个经典示例是当内存使用率过高时您希望被垃圾收集的缓存(通常使用 实现WeakHashMap
)。
Be sure to check out SoftReference
and PhantomReference
as well.
一定要检查出SoftReference
并PhantomReference
为好。
EDIT:Tom has raised some concerns over implementing a cache with WeakHashMap
. Here is an article laying out the problems: WeakHashMap is not a cache!
编辑:Tom 对使用WeakHashMap
. 这是一篇阐述问题的文章:WeakHashMap 不是缓存!
Tom is right that there have been complaintsabout poor Netbeans performance due to WeakHashMap
caching.
Tom 是对的,有人抱怨由于WeakHashMap
缓存导致 Netbeans 性能不佳。
I still think it would be a good learning experience to implement a cache with WeakHashMap
and then compare it against your own hand-rolled cache implemented with SoftReference
. In the real world, you probably wouldn't use either of these solutions, since it makes more sense to use a 3rd party library like Apache JCS.
我仍然认为WeakHashMap
使用SoftReference
. 在现实世界中,您可能不会使用这些解决方案中的任何一个,因为使用Apache JCS 之类的 3rd 方库更有意义。
回答by ???
[EDIT2]I found another good example of WeakReference
. Processing Bitmaps Off the UI Threadpage in Displaying Bitmaps Efficientlytraining guide, shows one usage of WeakReference
in AsyncTask.
[EDIT2]我发现了另一个很好的例子WeakReference
。在Displaying Bitmaps Efficiently培训指南中从 UI 线程页面处理位图显示WeakReference
了 AsyncTask 中的一种用法。
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);
}
}
}
}
It says,
它说,
The WeakReference to the ImageView ensures that the AsyncTask does not prevent the ImageView and anything it references from being garbage collected. There's no guarantee the ImageView is still around when the task finishes, so you must also check the reference in onPostExecute(). The ImageView may no longer exist, if for example, the user navigates away from the activity or if a configuration change happens before the task finishes.
对 ImageView 的 WeakReference 确保 AsyncTask 不会阻止 ImageView 及其引用的任何内容被垃圾收集。无法保证任务完成时 ImageView 仍然存在,因此您还必须检查 onPostExecute() 中的引用。ImageView 可能不再存在,例如,如果用户导航离开活动或者在任务完成之前发生配置更改。
Happy coding!
快乐编码!
[EDIT]I found a really good example of WeakReference
from facebook-android-sdk. ToolTipPopupclass is nothing but a simple widget class that shows tooltip above anchor view. I captured a screenshot.
[编辑]我WeakReference
从facebook-android-sdk找到了一个很好的例子。ToolTipPopup类只不过是一个简单的小部件类,它在锚视图上方显示工具提示。我截取了屏幕截图。
The class is really simple(about 200 lines) and worthy to look at. In that class, WeakReference
class is used to hold reference to anchor view, which makes perfect sense, because it makes possible for anchor view to be garbage collected even when a tooltip instance lives longer than its anchor view.
这个类真的很简单(大约 200 行),值得一看。在那个类中,WeakReference
class 用于保存对锚视图的引用,这是非常有意义的,因为即使工具提示实例的生命周期长于其锚视图,锚视图也可以被垃圾收集。
Happy coding! :)
快乐编码!:)
Let me share one working example of WeakReference
class. It's a little code snippet from Android framework widget called AutoCompleteTextView
.
让我分享一个WeakReference
班级的工作例子。这是来自 Android 框架小部件的一小段代码片段,名为AutoCompleteTextView
.
In short,WeakReference
class is used to holdView
object to prevent memory leakin this example.
简而言之,在这个例子中,WeakReference
类是用来保存View
对象的,以防止内存泄漏。
I'll just copy-and-paste PopupDataSetObserver class, which is a nested class of AutoCompleteTextView
. It's really simple and the comments explains the class well. Happy coding! :)
我只会复制并粘贴 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());
}
};
}
And the PopupDataSetObserver
is used in setting adapter.
而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);
}
One last thing. I also wanted to know working example of WeakReference
in Android application, and I could find some samples in its official sample applications. But I really couldn't understand some of them's usage. For example, ThreadSampleand DisplayingBitmapsapplications use WeakReference
in its code, but after running several tests, I found out that the get() method never returns null
, because referenced view object is recycled in adapters, rather then garbage collected.
最后一件事。我也想知道WeakReference
在 Android 应用程序中的工作示例,我可以在其官方示例应用程序中找到一些示例。但我真的无法理解其中的一些用法。例如,ThreadSample和DisplayingBitmaps应用程序WeakReference
在其代码中使用,但经过多次测试,我发现 get() 方法永远不会返回null
,因为引用的视图对象在适配器中被回收,而不是垃圾收集。
回答by Akshay
A "canonicalized" mapping is where you keep one instance of the object in question in memory and all others look up that particular instance via pointers or somesuch mechanism. This is where weaks references can help. The short answer is that WeakReferenceobjects can be used to create pointers to objects in your system while still allowing those objects to be reclaimed by the garbage-collectoronce they pass out of scope. For example if I had code like this:
“规范化”映射是您将所讨论对象的一个实例保留在内存中,而所有其他实例通过指针或某种此类机制查找该特定实例。这是弱引用可以提供帮助的地方。简短的回答是WeakReference对象可用于创建指向系统中对象的指针,同时仍然允许这些对象在超出范围时被垃圾收集器回收。例如,如果我有这样的代码:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( object );
}
}
Any object I register will never be reclaimed by the GC because there is a reference to it stored in the set of registeredObjects
. On the other hand if I do this:
我注册的任何对象都不会被 GC 回收,因为在registeredObjects
. 另一方面,如果我这样做:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( new WeakReference(object) );
}
}
Then when the GC wants to reclaim the objects in the Set it will be able to do so. You can use this technique for caching, cataloguing, etc. See below for references to much more in-depth discussions of GC and caching.
然后当 GC 想要回收 Set 中的对象时,它将能够这样做。您可以使用此技术进行缓存、编目等。有关 GC 和缓存的更深入讨论的参考,请参见下文。
回答by Suragch
Some of the other answers seem incomplete or overly long. Here is a general answer.
其他一些答案似乎不完整或过长。这是一个通用的答案。
How to use WeakReference in Java and Android
如何在 Java 和 Android 中使用 WeakReference
You can do the following steps:
您可以执行以下步骤:
- Create a
WeakReference
variable - Set the weak reference
- Use the weak reference
- 创建
WeakReference
变量 - 设置弱引用
- 使用弱引用
Code
代码
MyClass
has a weak reference to AnotherClass
.
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
has a strong reference to MyClass
.
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);
}
}
Notes
笔记
- The reason you need a weak reference is so that the Garbage Collector can dispose of the objects when they are no longer needed. If two objects retain a strong reference to each other, then they can't be garbage collected. This is a memory leak.
- If two objects need to reference each other, object A (generally the shorter lived object) should have a weak reference to object B (generally the longer lived object), while B has a strong reference to A. In the example above,
MyClass
was A andAnotherClass
was B. - An alternative to using a
WeakReference
is to have another class implement an interface. This is done in the Listener/Observer Pattern.
- 您需要弱引用的原因是垃圾收集器可以在不再需要对象时处理它们。如果两个对象彼此保持强引用,则它们不能被垃圾收集。这是内存泄漏。
- 如果两个对象需要相互引用,对象 A(通常是寿命较短的对象)应该对对象 B(通常是寿命较长的对象)有一个弱引用,而 B 对 A 有一个强引用。在上面的例子中,
MyClass
是 A并且AnotherClass
是 B。 - 使用 a 的替代方法
WeakReference
是让另一个类实现一个接口。这是在Listener/Observer Pattern 中完成的。