我正在更新Volley onResponse
回调中的一个集合,如下所示:
@Override
public void onResponse(String response)
{
if (!response.equals(Properties.PRODUCT_NOT_FOUND) || !response.equals(Properties.USER_NOT_FOUND))
{
if (user.getFavoriteProducts().contains(product.getId()))
{
user.getFavoriteProducts().remove(product.getId());
} else {
user.getFavoriteProducts().add(product.getId());
}
mSharedPreferencesManager.insertUser(user);
}
}
当同时收到两个响应时,同时加入该组。我试图让这个设置线程安全,但我无法让它工作,这是我迄今为止所尝试的:
使用SynchronizedSet:
user.setFavoriteProducts(Collections.synchronizedSet(new HashSet<Long>()));
使用CopyOnWriteArraySet:
user.setFavoriteProducts(new CopyOnWriteArraySet<Long>());
同步回调中的代码:
private static final Object object = new Object();
@Override
public void onResponse(String response)
{
synchronized (object)
{
if (!response.equals(Properties.PRODUCT_NOT_FOUND) || !response.equals(Properties.USER_NOT_FOUND))
{
if (user.getFavoriteProducts().contains(product.getId()))
{
user.getFavoriteProducts().remove(product.getId());
} else {
user.getFavoriteProducts().add(product.getId());
}
mSharedPreferencesManager.insertUser(user);
}
}
}
这些都没有奏效,任何帮助都会受到赞赏!
编辑:什么不起作用的是只插入了一个项目。
编辑2 :我已经尝试了N0un的方法,但仍然只插入了一个项目
这是我使用的代码:
@Override
public void onResponse(final String response)
{
Log.d(Properties.TAG, "[REST_CLIENT] Response received: " + response);
AsyncTask.execute(new Runnable()
{
@Override
public void run()
{
synchronized (RestClient.class)
{
if (!response.equals(Properties.PRODUCT_NOT_FOUND) || !response.equals(Properties.USER_NOT_FOUND))
{
if (user.getFavoriteProducts().contains(product.getId()))
{
Log.d(Properties.TAG, "[REST_CLIENT] Removing product from favorites: " + product.getId());
user.getFavoriteProducts().remove(product.getId());
} else {
Log.d(Properties.TAG, "[REST_CLIENT] Adding product to favorites: " + product.getId());
user.getFavoriteProducts().add(product.getId());
}
Log.d(Properties.TAG, "[REST_CLIENT] Updating user");
mSharedPreferencesManager.insertUser(user);
Log.d(Properties.TAG, "[REST_CLIENT] Set size: " + user.getFavoriteProducts().size());
}
}
}
});
}
这些是我得到的日志:
D/CUOKA: [REST_CLIENT] Response received: ACCEPTED
D/CUOKA: [REST_CLIENT] Adding product to favorites: 3921
D/CUOKA: [REST_CLIENT] Updating user
D/CUOKA: [REST_CLIENT] Response received: ACCEPTED
D/CUOKA: [REST_CLIENT] Set size: 1
D/CUOKA: [REST_CLIENT] Adding product to favorites: 2361
D/CUOKA: [REST_CLIENT] Updating user
D/CUOKA: [REST_CLIENT] Set size: 1
编辑3 :这是将用户插入SharedPreferences的代码:
public synchronized boolean insertUser(final User user)
{
mEditor = mSharedPreferences.edit();
Gson gson = new Gson();
String json = gson.toJson(user);
mEditor.putString(KEY_USER, json);
return mEditor.commit();
}
答案 0 :(得分:0)
好吧,使用经典Java Executor
在UI线程中调用Volley的侦听器。我认为有一种机制可以在UI线程中有太多工作时取消一些监听器调用。
试试:
@Override
public void onResponse(String response)
{
AsyncTask.execute(new Runnable() {
@Override
public void run()
{
synchronized (MyClassName.class) {
if (!response.equals(Properties.PRODUCT_NOT_FOUND)
|| !response.equals(Properties.USER_NOT_FOUND)) {
if (user.getFavoriteProducts().contains(product.getId())) {
user.getFavoriteProducts().remove(product.getId());
} else {
user.getFavoriteProducts().add(product.getId());
}
mSharedPreferencesManager.insertUser(user);
}
}
}
});
}
只需将在侦听器中执行的数据处理移动到后台线程/ AsyncTask即可释放UI线程并防止阻塞。
编辑:经过一些讨论和代码审核后,我发现了(第二个)问题:在请求之前检索到user
并且线程安全问题就在这里。新请求正在进行时,user
的数据尚未保存。因此,第二个请求与第一个请求相同Set
,而不是新更新的Set
。所以user
应该在我建议的synchronized
区块中检索,然后再进行其他处理。
答案 1 :(得分:-1)
监听器正在使用Main Thread
(UI线程),因此可能会发生某种阻塞。您应该将数据处理移动到后台线程或使处理异步。
关于设置同步,您应该使用ConcurentHashMap
,并使用集合中的newSetFromMap()
方法简单地包装Set。