0

我一直在尝试WeakReference在我的 Android 项目中使用,但从未取得任何成功。现在我真的需要它,因为我正在处理旧设备,我必须尽可能保持内存清洁。

无论如何,我有一个数组,其中包含大约 1000 个不同字符串的列表。我需要加载它然后在其中找到一个字符串。

这就是我目前使用它的方式:

String[] campaignList = context.getResources().getStringArray(R.array.campaignList);
WeakReference<String[]> weakCampaignList = new WeakReference<String[]>(campaignList);

这是正确的使用方法WeakReference吗?如果是,那么我不明白的是阵列正在水合,String[]然后我将它传递给WeakReference. 那么这是否意味着我在分配给一个数组的内存中有 2 个点?还是我完全误解了这个WeakReference概念?

我在所有资源中发现的一个非常好的资源是这个:

http://neverfear.org/blog/view/150/Strong_Soft_Weak_and_Phantom_References_Java

编辑:

我的代码没有问题。只需要知道我在性能方面是否正确。

for (int i = 0; i < weakCampaignList.get().length; i++) {
  Log.d(TAG,"weakCampaignList: "+weakCampaignList.get()[i]);
}

我的整个方法

public static String getTheCampaign(String country, Context context) {
        String campaign = "";
        campaign = "annual_subscription_" + country;

        String[] campaignList = context.getResources().getStringArray(
                R.array.campaign_list);

        ArrayList<WeakReference<String>> weakCampaignList = new ArrayList<WeakReference<String>>();
        for (String s : campaignList) {
            weakCampaignList.add(new WeakReference<String>(s));
        }

        if (country.equals("") || country.isEmpty()) {
            campaign = "annual_subscription_us";
        } else {
            for (int i = 0; i < weakCampaignList.size(); i++) {
                if (weakCampaignList.get(i).get().contains(campaign)) {
                    campaign = weakCampaignList.get(i).get();
                    return campaign;
                } 
            }
        }
        return campaign;
    }
4

3 回答 3

5

In garbage collected languages such as Java, weak references are often used to prevent static or long-lived objects from causing memory to never be released. For example, suppose your application contained a singleton class ClipboardMonitor that kept track of the last document where the user pressed Ctrl+C.

class ClipboardMonitor {
    static Document lastDocument;

    // return the last document where Ctrl+C was pressed
    static Document getLastDocument() {
        return lastDocument;
    }

    static void copyCommand(Document document) {
        lastDocument = document;
    }
}

In this implementation, if the user presses Ctrl+C and then closed the document window (but not the application), the lastDocument field would keep holding a reference to the document and the garbage collector could not reclaim that memory. Weak references can resolve that problem.

In the following modified code, the static field lastDocument is turned into a weak reference, so even if the user presses Ctrl+C and a document is assigned to this field the garbage collector can reclaim the document memory after the document is closed.

class ClipboardMonitor {
    static WeakReference<Document> lastDocument;

    // return the last document where Ctrl+C was pressed, or null if
    // that document was closed and the garbage collector has already
    // reclaimed the memory
    static Document getLastDocument() {
        WeakReference<Document> weakDocument = lastDocument;
        return weakDocument != null ? weakDocument.get() : null;
    }

    static void copyCommand(Document document) {
        lastDocument = new WeakReference<Document>(document);
    }
}

This example highlights the most important point about weak references: weak references do not save memory all by themselves. Rather, they are used to resolve a particular type of problem that can cause apparent memory leaks in an application written in a garbage collected language. If your application design does not require the use of weak references to address particular design limitations, then adding weak references will only have one (or more) of the following consequences:

  1. Increase the memory requirements of your application
  2. Increase the CPU requirements of your application
  3. Introduce difficult to reproduce bugs when objects you still need to use get unexpectedly garbage collected

The code in the original post does not contain information or evidence to determine whether or not you need to use weak references, nor does it provide the information necessary to show their correct use in addressing a particular constraint of your application. The information above is general commentary on weak references that may help you understand how to proceed.

Edit: Based on the updated method you posted, it appears that weak references are not necessary in your case. They are not providing any benefits, and are causing at least problems 1 and 2 from the list above. Depending on the particular garbage collector implementation, they may result in problem 3 as well (throwing a NullPointerException when you try to call contains).

于 2013-06-07T02:10:25.883 回答
0

您需要根据您对正确行为的要求来考虑这一点。特别是,如果一个单独的字符串被垃圾收集,而你试图找到它,会发生什么?

如果你打算使用它,你需要通过压力测试来测试它——确保弱引用被垃圾收集。在您这样做之前,您并不真正知道它是否正常工作。

如果您无法重新加载列表中的单个条目,您可能希望对整个列表有一个 WeakReference。然后每当您需要访问它时,您需要查看它是否已被 gc'ed,如果是则重新加载它。

你写了:

if (weakCampaignList.get(i).get().contains(campaign)) {
                campaign = weakCampaignList.get(i).get();

每当您检查引用上的 get() 是否为非空时,将结果保存在变量中并在之后使用它;不要做第二个 get() 假设引用仍然存在。不会是每一次的蓝月亮 - 垃圾收集器在此期间捡起它。如果您持有一个包含参考内容的变量,那将不会发生。

在您真正确信自己理解它们之前,我不会在生产代码中使用 Wea​​kReferences。

于 2013-06-07T02:48:46.197 回答
0

尝试这个

String[] campaing_list ....

        ArrayList<WeakReference<String>> list = new ArrayList<WeakReference<String>>();
        for (String s : campaing_list) {
            list.add(new WeakReference<String>(s));
        }
于 2013-06-07T00:40:50.127 回答