Почему я получаю исключение java.lang.IndexOutOfBoundsException при попытке получить элемент jsonArray? - PullRequest
1 голос
/ 30 мая 2019

В моем приложении есть что-то вроде прикрепления файлов к сообщениям. Эти прикрепленные файлы отображаются в RecyclerView с адаптером. Каждый элемент RV имеет свой собственный btn для его удаления. Проблема в том, что у меня в списке есть два элемента, и я пытаюсь удалить 1 элемент, а не 2, я получаю сообщение об ошибке. Но когда я пытаюсь удалить 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 () выдает это исключение:

enter image description here

почему это происходит и как я могу решить эту ошибку. Я пытался изменить это: for (i in 0 until array.size()) к этому for (i in 0 until array.size()-1) и это не сработало. Затем я попытался изменить этот цикл на for (i in 1 until array.size()), и это тоже не помогло. Итак, где я допустил ошибку и как я могу предотвратить эту проблему в будущем?

P.S. Извините за прикрепление скриншота отладчика, потому что я не смог получить от него текстовые данные.

Ответы [ 4 ]

3 голосов
/ 30 мая 2019

Вы используете метод remove внутри итерации цикла for, который динамически изменяет размер массива.

Если вам нужно удалить только один элемент, обратитесь к ответу @ 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)
}
3 голосов
/ 30 мая 2019

Вы удалили элемент из исходного массива, поэтому вы получаете исключение, поэтому используйте новый массив для отфильтрованных значений

Проблема в строке ниже

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)


}
1 голос
/ 30 мая 2019

Просто добавьте оператор break в условие if.

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;
   }

 }
}

Причина, по которой вы получаете исключение после удаления первого элемента, состоит в том, что цикл выполняется после удаления первого элемента.
Но если у вас был разрыв, он не будет выполняться в следующий раз.
Причина, по которой вы не получаете исключение при попытке удаления второго элемента цикл заканчивается ровно после удаления второго элемента.

0 голосов
/ 30 мая 2019

Дорогие друзья, мне кажется, что мне удалось решить эту проблему, но я не уверен, поэтому мне нужна ваша проверка.Итак, я добавил оператор возврата в моем состоянии:

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
}

, поэтому при выполнении этого условия я возвращаюсь из процесса удаления.Я думаю, что знаю, почему мое приложение иногда зависало - я нажимаю yes в диалоговом окне предупреждений, и мой объект был удален из массива, но мой цикл продолжает работать и проверять.Но, может быть, я снова ошибаюсь:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...