【问题标题】:Why I'm getting java.lang.IndexOutOfBoundsException when I try to get an item of jsonArray?为什么当我尝试获取 jsonArray 项时出现 java.lang.IndexOutOfBoundsException?
【发布时间】:2019-05-30 05:09:21
【问题描述】:

在我的应用程序中,我喜欢将文件附加到消息中。这些附加文件显示在带有适配器的 RecyclerView 中。 RV 的每个项目都有自己的 btn 用于删除它。问题是当我的列表中有两项并尝试删除一项而不是第二项时,我收到了错误。但是当我尝试删除第 2 项然后第 1 项时,一切正常。我使用调试器并设法找到有问题的行,但我不知道如何解决这个问题。因此,这是适配器中用于从列表中删除项目的代码:

val array = Singleton.array
if (array!!.size() > 0) {
  for (i in 0 until array.size()) {
   val obj = array.get(i).asJsonObject

   if (obj.get("filename").toString().substring(1, obj.get("filename").toString().length - 1) == mNames[position]) {
   array.remove(obj)
   mNames.removeAt(position)
   Singleton.array = array
   updateNames(mNames)
   }

 }
}

我在这行有问题:

val obj = array.get(i).asJsonObject

我通过记录器检查了这个变量,一切似乎都很好,我可以用 0 索引获得值。然后我认为问题出在我向适配器发送数据的地方,但一切正常。我使用了调试器,发现 getAsJsonObject() 方法抛出了这个异常:

为什么会发生,我该如何解决这个错误。我试图改变这一点: for (i in 0 until array.size()) 到这个 for (i in 0 until array.size()-1) 并没有用。然后我尝试将此循环更改为for (i in 1 until array.size()),但它也没有帮助。那么,我在哪里犯了错误以及将来如何防止这个问题?

附:很抱歉附上了调试器的截图,因为我无法从中获取文本数据。

【问题讨论】:

  • Java/Kotlin 中的元素编号是 0...length-1所以如果你的数组大小是 10,你可以获得 0...9 个元素。检查您的for (i in 0 until array.size()) { 条件
  • 您正在从数组中删除一个元素,同时迭代它,因此它的大小会发生变化。尝试直接从 Singleton.array 中删除或复制数组以进行迭代并从原始数组中删除。
  • @Arun,你能检查我的答案吗?也许它会解决我的问题?
  • @VladyslavMatviienko,我看到问题与从数组中删除项目的过程有关,这意味着当我已经删除它的项目时我的循环继续进行,所以我决定使用 break/return from loop当项目被删除时,我的回答显示了这个方法
  • @AndrewGoroshko 我认为只要您只删除一项,您的答案就应该有效。

标签: android arrays kotlin android-recyclerview


【解决方案1】:

您已从源数组中删除元素,这就是为什么您会出现异常,因此请为过滤后的值使用新数组

下面一行的问题

array.remove(obj)

解决方案:

val positionsForRemove = ArrayList<Int>(),
val array = Singleton.array
if (array!!.size() > 0) {
   for (i in 0 until array.size()) {
     val obj = array.get(i).asJsonObject
     if (obj.get("filename").toString().substring(1, obj.get("filename").toString().length - 1) == mNames[position]) 
       positionsForRemove.add(position)
    }
   for(position in positionsForRemove){
          array.remove(position)
          mNames.remove(position)   
        }
  Singleton.array = array
  updateNames(mNames)


}

【讨论】:

  • 那么,我可以在哪里插入这个新的数组用法?
  • 声明新数组或 MutableList 并将所有数组元素添加到其中。和 newList.remove(obj);完成 for 循环后,您可以在单例上恢复它
  • 但是删除数组项后返回呢?它可以帮助我吗?还是数组声明更好?
  • 是的,我已经更新了答案,现在试试吧。 for loop { 放错了位置。现在它会为你工作
  • 那么它比我在下面发布的解决方案更好吗?您的解决方案也运行良好,但为什么会更好?
【解决方案2】:

您在 for 循环迭代中使用 remove 方法,该方法动态更改数组大小。

如果您只需要删除一项,请参考@Jeeva 的回答。

如果你想一次从列表中删除多个位置,你必须参考下面的方法从数组中删除项目,.

val removePositions = ArrayList<Int>(),
val array = Singleton.array
if (array!!.size() > 0) {
  for (i in 0 until array.size()) {
   val obj = array.get(i).asJsonObject

   if (obj.get("filename").toString().substring(1, obj.get("filename").toString().length - 1) == mNames[position])
   //array.remove(obj)
   //mNames.removeAt(position)
   removePositions.add(position)
   //Singleton.array = array
   //updateNames(mNames)
  }

  for (i in 0 until removePositions.size()) {
    array.remove(removePositions[i])
    mNames.remove(removePositions[i])
  }
  Singleton.array = array
  updateNames(mNames)
}

【讨论】:

  • @AndrewGoroshko,你在上面的代码中遇到了什么错误?
  • @AndrewGoroshko,抱歉代码有点放错了。现在尝试使用固定代码。
【解决方案3】:

只需在 if 条件中添加 break 语句即可。

val array = Singleton.array
if (array!!.size() > 0) {
  for (i in 0 until array.size()) {
   val obj = array.get(i).asJsonObject

   if (obj.get("filename").toString().substring(1, obj.get("filename").toString().length - 1) == mNames[position]) {
   array.remove(obj)
   mNames.removeAt(position)
   Singleton.array = array
   updateNames(mNames)
   break;
   }

 }
}

删除第一个元素后出现异常的原因是删除第一个元素后执行了循环。
但是如果你有break,下次它不会执行。
你没有得到异常的原因尝试删除第二个元素是循环在删除第二个元素后恰好结束。

【讨论】:

    【解决方案4】:

    亲爱的朋友,我似乎设法解决了这个问题,但我不确定,所以我需要你的检查。所以,我在我的条件中添加了 return 语句:

    if (obj.get("filename").toString().substring(1, obj.get("filename").toString().length - 1) == mNames[position]) {
    array.remove(obj)
    mNames.removeAt(position)
    Singleton.array = array
    updateNames(mNames)
    return@setButton
    }
    

    所以当我满足这个条件时,我会从删除过程中返回。我想我知道为什么我的应用程序有时会崩溃 - 我在警报对话框中按是 btn 并且我的对象已从数组中删除,但我的循环继续工作和检查。但也许我又错了:)

    【讨论】:

    • 只是使用break语句兄弟。
    • 在哪里?而不是返回?
    • 是的,您正在将此代码用于删除按钮,删除按钮后将立即使用一次,为什么要继续迭代 for 循环。执行 if 条件后只需使用 break
    • 我的方法可以解决这个问题还是上面的用户也给了有用的建议?
    • 我建议你做其他方式:而不是 on-the-;fly 从数组中删除项目,首先将要删除的项目收集到另一个数组中,然后仅在循环之后 - 删除项目
    猜你喜欢
    • 2020-02-25
    • 2014-08-31
    • 1970-01-01
    • 1970-01-01
    • 2012-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多