Chr*_*ris 159 java android weak-references
我是一名Java开发人员已有2年.
但我从来没有在我的代码中写过WeakReference.如何使用WeakReference使我的应用程序更高效,尤其是Android应用程序?
dby*_*rne 224
使用WeakReferenceAndroid中并不比普通的旧Java中使用一个什么不同.这是一个很好的指南,它给出了详细的解释:理解弱引用.
你应该考虑使用一个每当你需要一个对象的引用,但你不希望引用要保护的对象从垃圾收集器.一个典型的例子是当内存使用率过高时(通常用它实现WeakHashMap),你想要垃圾收集的缓存.
一定要检查出SoftReference并PhantomReference为好.
编辑:汤姆已经提出了一些关于实现缓存的担忧WeakHashMap.这是一篇文章,列出了问题:WeakHashMap不是缓存!
汤姆是正确的,有过投诉约差NetBeans性能的因WeakHashMap缓存.
我仍然认为这将是一个很好的学习经验,以实现与高速缓存WeakHashMap,然后把它比对与实现自己的手卷缓存SoftReference.在现实世界中,你可能不会使用这两种解决方案,因为它使使用第三方库像更有意义的Apache JCS.
김준호*_*김준호 62
[EDIT2]我找到了另一个很好的例子WeakReference.处理位图显示位图中的UI线程页面高效地训练指南,显示WeakReferenceAsyncTask中的一种用法.
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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
它说,
对ImageView的WeakReference确保AsyncTask不会阻止ImageView及其引用的任何内容被垃圾回收.当任务完成时,无法保证ImageView仍然存在,因此您还必须检查onPostExecute()中的引用.ImageView可能不再存在,例如,用户导航离开活动或者在任务完成之前发生配置更改.
快乐的编码!
[编辑]我WeakReference从facebook-android-sdk找到了一个非常好的例子.ToolTipPopup类只是一个简单的窗口小部件类,它在锚点视图上方显示工具提示.我抓了一个截图.

该课程非常简单(约200行),值得一看.在该类中,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());
}
};
}
Run Code Online (Sandbox Code Playgroud)
并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);
}
Run Code Online (Sandbox Code Playgroud)
最后一件事.我也想知道WeakReferenceAndroid应用程序中的工作示例,我可以在其官方示例应用程序中找到一些示例.但我真的无法理解它们中的一些用法.例如,ThreadSample和ShowingBitmaps应用程序WeakReference在其代码中使用,但在运行多个测试之后,我发现get()方法永远不会返回null,因为引用的视图对象在适配器中被回收,而不是垃圾回收.
Sur*_*gch 15
其他一些答案似乎不完整或过长.这是一般性答案.
您可以执行以下步骤:
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
}
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
MyClass是A并且AnotherClass是B.WeakReference是让另一个类实现一个接口.这是在Listener/Observer模式中完成的."规范化"映射是指将内存中的一个对象实例保存在内存中,而其他所有实例都通过指针或某种机制查找该特定实例.这是弱参考可以帮助的地方.简短的回答是,WeakReference对象可用于创建指向系统中对象的指针,同时仍允许垃圾收集器在超出范围时回收这些对象.例如,如果我有这样的代码:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( object );
}
}
Run Code Online (Sandbox Code Playgroud)
我注册的任何对象都不会被GC回收,因为存储在该组中的对它的引用registeredObjects.另一方面,如果我这样做:
class Registry {
private Set registeredObjects = new HashSet();
public void register(Object object) {
registeredObjects.add( new WeakReference(object) );
}
}
Run Code Online (Sandbox Code Playgroud)
然后,当GC想要回收Set中的对象时,它将能够这样做.您可以使用此技术进行缓存,编目等.请参阅下文,以获取有关GC和缓存的更深入讨论的参考.
| 归档时间: |
|
| 查看次数: |
84812 次 |
| 最近记录: |