java - IndexOutOfBoundsException 后检查

标签 java android list

我遇到了这个异常:

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/

相关文章:

java - 由 JNI_CreateJavaVM() 启动的线程数

Android:唤醒锁:是否在应用程序暂停时释放锁?

带圆角的 Android 圆形进度条

list - Prolog,列表中 Y 之前的 X

list - 在 Haskell 中生成一组 bool 变量的所有组合

java - 当请求的页面或方法找不到时如何定义全局页面?

java - 加载资源在本地有效,但在服务器上无效

android - 如何通过安卓设备上传文件到wowza媒体服务器?

Java Lambda 表达式 参数数据类型

java - Android 客户端向 C 套接字服务器发送对象失败