我正在尝试在Android应用程序中实现缓存。我添加了一个静态全局数组

public static State[][] stateList = new State[Country.values().length][];

这里的国家/地区始终是固定的,因此我做了一个枚举,但是状态经常会不时更改,因此我从服务器(具有一个不错的后端,可以在其中编辑/添加/删除状态)中提取数据。

我有一个简单的国家/地区下拉列表,下面有一个列表 View ,选择后会自动更改。我目前的实现方式是这样的纯网络请求...
new FetchStatesTask(this, country, mProgressBar, view).execute();

它在网络获取期间显示进度条,然后onPostExecute将其停止,然后制作一个回调onStatesFetched(State[] states),该代码具有可正确重新填充listview的代码。

但是我想实现缓存,所以想法是将获取的数据存储在stateList数组中。我最初的想法是做这样的事情。
if(stateList[country] == null)
  // Do network request FetchStatesTask and then call onStatesFetched with result
else
  // Directly call doStatesFetched passing stateList[country]

但我正在寻找一种替代方案。
public static State[] getStateList[]
{
if(stateList[country] == null)
  // Do network request FetchStatesTask and then return State[] after async operation
else
  // Return stateList[country]
}

这样,我可以删除回调监听器,并使用一个函数来完成获取状态和返回的整个过程,并且在已经将stateList缓存在数组中的情况下同步进行操作,或者如果以前没有缓存,则进行异步操作。我不确定如何实现上述逻辑,因此将不胜感激。谢谢

最佳答案

您最初的想法很好,因为正如您所说的,它在dropdown in android app中使用,因此不会同时执行许多此类操作。把事情简单化。但是最好将State[][] stateList声明为volatile。因为根据Java内存模型volatile给出了“可见性保证”。
这是简短的说明"What does volatile do?"

如果您仍然想使用State[] getStateList(),而不是使用Double Checked Locking样式

private static volatile String[][] stateList;
...

public State[] getStateList() {
    if (stateList[country] == null) {
        synchronized (this) {
            if (stateList[country] == null) {
                // Do network request FetchStatesTask and then return State[] after async operation
            }
        }
    }
    return stateList[country];
}

但是在这种情况下,我无法理解为什么您需要“在异​​步操作之后返回ReturnState []”,因为这种函数签名意味着在getStateList()情况下线程进入stateList[country] == null之后,该线程将在async operation完成之前等待,并且仅在此之后。 return State[]。因此,调用State[] getStateList()总是会同步(更准确地说是阻止)。如果method返回非void值并等待完成阻塞操作,则它不能是非阻塞的,或者如您所说的async if not cached before
因此,您每次都使用您的原始想法,或者每次都使用FetchStatesTask(持有stateList缓存),并且仅在其为空时才进行网络请求。

09-10 23:47