我正在尝试在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
缓存),并且仅在其为空时才进行网络请求。