我在一份分析报告中得到了下面的错误,我很难弄清楚它是从哪里来的,或者是如何解决的。
我感到困惑的原因是,崩溃似乎引用了它-self的Volley库,而不是我实际编写的任何代码(崩溃中没有任何代码指向我的代码)。
有谁知道我怎样或者怎样才能解决这场坠机?
如有任何建议,将不胜感激。
致命错误:
Fatal Exception: java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:787)
at java.util.HashMap$ValueIterator.next(HashMap.java:819)
at com.android.volley.toolbox.ImageLoader$4.run(ImageLoader.java:464)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5527)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)来源:
public class VolleyManager {
private static final String TAG = VolleyManager.class.getSimpleName();
/** Number of network request dispatcher threads to start. */
private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;
private static VolleyManager mInstance;
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private static Context mContext;
private VolleyManager(Context context) {
mContext = context.getApplicationContext();
mRequestQueue = getRequestQueue();
}
public static synchronized VolleyManager getInstance(Context context) {
if (mInstance == null) {
mInstance = new VolleyManager(context);
}
return mInstance;
}
@SuppressWarnings("deprecation")
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
File cacheDir = new File(FMCacheManager.getCacheBaseDir(mContext));
String userAgent = "volley/0";
try {
String packageName = mContext.getPackageName();
PackageInfo info = mContext.getPackageManager().getPackageInfo(packageName, 0);
userAgent = packageName + "/" + info.versionCode;
} catch (NameNotFoundException ignore) {
}
HttpStack stack = new HurlStack();
Network network = new BasicNetwork(stack);
HandlerThread mHandlerThread = new HandlerThread(TAG, android.os.Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
ResponseDelivery delivery = new ExecutorDelivery(new Handler(mHandlerThread.getLooper()));
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network, DEFAULT_NETWORK_THREAD_POOL_SIZE, delivery);
queue.start();
mRequestQueue = queue;
}
return mRequestQueue;
}
public ImageLoader getImageLoader() {
getRequestQueue();
if (mImageLoader == null) {
mImageLoader = new ImageLoader(this.mRequestQueue,
new LruBitmapCache());
}
return this.mImageLoader;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
if (req != null) {
Log.d(TAG, "request: " + req.getUrl());
// set the default tag if tag is empty
req.setTag(FMUtils.isNullOrEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}发布于 2016-05-23 18:18:32
是的,堆栈跟踪表明崩溃发生在ImageLoader的run()方法中,并且与在HashMap上迭代有关。
您可以看到(某些版本的) ImageLoader.java 在这里。每一个循环都是这样的:
for (BatchedImageRequest bir : mBatchedResponses.values()) {
for (ImageContainer container : bir.mContainers) {
// If one of the callers in the batched request canceled the request
// after the response was received but before it was delivered,
// skip them.
if (container.mListener == null) {
continue;
}
if (bir.getError() == null) {
container.mBitmap = bir.mResponseBitmap;
container.mListener.onResponse(container, false);
} else {
container.mListener.onErrorResponse(bir.getError());
}
}
}现在,如果另一个线程在迭代时修改mBatchedResponses.values()或bir.mContainers,则会出现ConcurrentModificationException。它们不是“线程安全”集合。
有最近的另一次讨论,它指出任何同时(并行)图像加载操作都应该使用单独的ImageLoader实例。费尔南多·贾斯科维奇写道:
您必须实现两个ImageLoaders,一个用于缩略图,另一个用于全分辨率图像。
因此,您可以检查是否在自己的代码中启动任何并行图像下载操作,查看其他讨论并遵循推荐的方法。
至于“如何诊断ConcurrentModificationException”的一个更通用的答案:查看堆栈跟踪,查看确切的代码文件名和行号。如果它在一个for-每一个循环中迭代一个集合,那么您可能同时在另一个线程中修改该集合。这种情况可能只是偶尔发生,而且在很长一段时间内没有人注意到。在修改上述每个循环中的集合时,也会发生同样的异常,例如,在这次讨论中。
https://stackoverflow.com/questions/37397276
复制相似问题