首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Java和Android开发中使用WeakReference?

如何在Java和Android开发中使用WeakReference?
EN

Stack Overflow用户
提问于 2010-07-14 11:26:57
回答 4查看 98.1K关注 0票数 176

我已经做了两年的java开发人员。

但是我从来没有在我的代码中编写过WeakReference。如何使用WeakReference使我的应用程序更高效,尤其是安卓应用程序?

EN

回答 4

Stack Overflow用户

发布于 2010-07-14 11:37:46

在Android中使用WeakReference与在普通的Java中使用没有什么不同。

当您需要一个对对象的引用,但又不想让该引用保护对象不被垃圾收集器攻击时,您应该考虑使用一个。一个典型的例子是,当内存使用率过高(通常使用WeakHashMap实现)时,您希望对缓存进行垃圾回收。

一定要检查一下SoftReferencePhantomReference

编辑: Tom提出了一些关于使用WeakHashMap实现缓存的问题。这里有一篇文章列出了这些问题:WeakHashMap is not a cache!

关于WeakHashMap缓存导致Netbeans性能不佳的complaints说法,Tom是对的。

我仍然认为,使用WeakHashMap实现缓存,然后将其与使用SoftReference实现的手动缓存进行比较,这将是一次很好的学习体验。在现实世界中,你可能不会使用这些解决方案中的任何一个,因为使用像Apache JCS这样的第三方库更有意义。

票数 235
EN

Stack Overflow用户

发布于 2015-04-12 22:51:48

EDIT2我发现了WeakReference的另一个很好的例子。Displaying Bitmaps Efficiently培训指南中的Processing Bitmaps Off the UI Thread页显示了WeakReference在AsyncTask中的一种用法。

代码语言:javascript
复制
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);
            }
        }
    }
}

上面写着,

WeakReference to ImageView可确保AsyncTask不会阻止ImageView及其引用的任何内容被垃圾收集。不能保证在任务完成时ImageView仍然存在,所以您还必须检查onPostExecute()中的引用。例如,如果用户离开了活动,或者在任务完成之前发生了配置更改,则ImageView可能不再存在。

祝你编码愉快!

编辑我从facebook-android-sdk中找到了一个非常好的WeakReference示例。ToolTipPopup类只是一个简单的窗口小部件类,它在锚视图上方显示工具提示。我截取了一张截图。

这个类非常简单(大约200行),值得一看。在该类中,WeakReference类用于保存对锚视图引用,这非常有意义,因为即使工具提示实例的生存期比其锚视图更长,也可以对锚视图进行垃圾回收。

编码愉快!:)

让我分享一个WeakReference类的工作示例。这是一小段来自Android framework widget的代码片段,叫做AutoCompleteTextView

简而言之,在本例中, WeakReference 类用于保存 View 对象,以防止

我将只复制粘贴AutoCompleteTextView的嵌套类PopupDataSetObserver类。它真的很简单,注释很好地解释了这个类。编码愉快!:)

代码语言:javascript
复制
    /**
     * 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用于设置适配器。

代码语言:javascript
复制
    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);
}

最后一件事。我还想知道WeakReference在安卓应用程序中的工作示例,我可以在它的官方示例应用程序中找到一些示例。但是我真的不能理解他们中的一些用法。例如,ThreadSampleDisplayingBitmaps应用程序在其代码中使用WeakReference,但是在运行了几个测试之后,我发现get()方法从不返回null,因为被引用的视图对象在适配器中被回收,而不是垃圾回收。

票数 69
EN

Stack Overflow用户

发布于 2017-10-31 11:36:50

其他一些答案似乎不完整或过于冗长。这是一个通用的答案。

如何在Java和Android中使用WeakReference

您可以执行以下步骤:

  1. 创建一个WeakReference变量
  2. 设置弱引用

代码

MyClassAnotherClass的引用很弱。

代码语言:javascript
复制
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
    }

}

AnotherClassMyClass有很强的引用。

代码语言:javascript
复制
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);
    }
}

备注

  • 您需要弱引用的原因是,当对象不再需要时,垃圾回收器可以将其处理掉。如果两个对象保持彼此的强引用,那么它们就不能被垃圾回收。这是一个内存泄漏。
  • 如果两个对象需要相互引用,对象A (通常是较短的对象)应该有一个对对象B(通常是较长的对象)的弱引用,而B有一个对A的强引用。在上面的例子中,MyClass是A,AnotherClass是B。
  • 使用WeakReference的替代方法是让另一个类实现一个接口。这是在Listener/Observer Pattern.

中完成的

实际例子

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3243215

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档