我遇到了这个异常:
java.lang.IndexOutOfBoundsException 索引 2 无效,大小为 0
bugsnag 报告该行是 RouteActivity.java:96us.example.serviceapp.tab.RouteActivity$2.handleMessage
疯狂的事情是我有 2 个点检查列表的 size()
方法,应该防止这种情况发生
progressbar.setProgress(0);
if (datalist.size() > 0) {
float all = 0;
for (int i = 0; i < datalist.size(); i++) {
all += datalist.get(i).getCompletionRate(); //line 96
}
progressbar.setProgress(Math.round(all / datalist.size()));
}
progressbar.refreshDrawableState();
所以我知道 i
是 2,第 96 行是 all += datalist.get(2).getCompletionRate();
并且错误消息说 datalist
大小为 0。
但是我不明白的是为什么第一次检查 datalist.size() > 0
评估为 true 甚至如果大小为 0 我怎么会变成 = 2。而且我还假设datalist.get(1)
在上一次迭代中被顺利调用。模型 getCompletionRate 方法不会更改数据列表。
public int getCompletionRate() {
return total > 0 ? Math
.round(((float) (total - remaining) / (float) total) * 100) : 0;
}
这种情况发生在一个正在运行的应用程序上,并且只发生在一小部分用户身上。 (1/100?)我不知道如何重现它,它甚至正在发生,这真的令人费解。我错过了什么?
最佳答案
听起来您拥有跨多个线程的共享数据结构。在您的 datalist.size() > 0
验证后,另一个线程可能正在重置 datalist
的大小。
假设是这种情况,您将需要使用互斥锁来避免这种情况。尝试查看 synchronized
statement .
例子:
private static final Object lock = new Object();
synchronized(lock) {
if (datalist.size() > 0) {
float all = 0;
for (int i = 0; i < datalist.size(); i++) {
all += datalist.get(i).getCompletionRate(); //line 96
}
progressbar.setProgress(Math.round(all / datalist.size()));
}
}
在您可能要清除此数据结构的其他位置:
synchronized(lock) {
datalist.clear();
}
这将确保 datalist
在您迭代它时永远不会被另一个线程重置。
关于java - IndexOutOfBoundsException 后检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29981323/