В моем приложении у меня есть что-то вроде прикрепления файлов к сообщениям. Эти прикрепленные файлы отображаются в RecyclerView с адаптером. У каждого элемента RV есть своя кнопка для его удаления. Проблема в том, что когда у меня есть два элемента в моем списке, и я пытаюсь удалить 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() выдает это исключение:
почему это происходит и как я могу решить эту ошибку. Я попытался изменить это:
for (i in 0 until array.size())
к этому for (i in 0 until array.size()-1)
и это не сработало. Потом попробовал поменять этот цикл на этот for (i in 1 until array.size())
и тоже не помогло. Итак, где я допустил ошибку и как я могу предотвратить эту проблему в будущем?
P.S. Извините, что прикрепляю скриншот отладчика, так как не смог получить из него текстовые данные.
Вы удаляете элемент из массива, перебирая его, поэтому его размер изменяется. Попробуйте удалить напрямую из Singleton.array или сделайте копию массива для итерации и удалите из оригинала.
@ Арун, можешь проверить мой ответ, пожалуйста? может это решит мою проблему?
@VladyslavMatviienko, я увидел, что проблема связана с процессом удаления элемента из массива, это означает, что мой цикл продолжается, когда я уже удалил его элемент, поэтому я решил использовать прерывание/возврат из цикла при удалении элемента, мой ответ показывает этот метод
@AndrewGoroshko Я думаю, ваш ответ должен работать, пока вы удаляете только один элемент.
@VladyslavMatviienko, но я не могу удалить несколько элементов, только один элемент без удаления группы
@AndrewGoroshko почему? ты можешь я уверен
@VladyslavMatviienko, почему ты уверен? Я могу удалить элемент, когда нажимаю кнопку удаления, и я могу удалить только один элемент из списка? Я не могу отметить несколько пунктов :)
@AndrewGoroshko ты имеешь в виду ты не можешь или ты не хочешь? Потому что я не вижу препятствий для удаления нескольких элементов
Я не могу, я уверен, и меня также удивляет, что вы уверены, потому что мне также интересно, как удалить несколько элементов :) например, когда у меня уже есть некоторые элементы, которые приходят из черновика сообщения и для удаление файла черновика я должен отправить запрос также на сервер
Какой класс array
? Если это коллекция, вы можете использовать метод array.removeAll(<collection to remove>)
для удаления нескольких элементов. Также, как показано Rajasekaran M
, вы можете использовать цикл для удаления нескольких элементов.
логически подтверждено, что я не могу удалить несколько элементов, один клик = один элемент
Дорогие друзья, кажется, мне удалось решить эту проблему, но я не уверен, поэтому мне нужна ваша проверка. Итак, я добавил оператор возврата в свое условие:
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
}
поэтому, когда я встречаю это условие, я возвращаюсь из процесса удаления. Я думаю, что я знаю, почему мое приложение иногда дает сбой - я нажимаю да в моем диалоговом окне предупреждения, и мой объект был удален из массива, но мой цикл продолжает работать и проверять. Но может я опять ошибаюсь :)
просто используйте оператор break, братан.
куда? вместо возврата?
да, вы используете этот код для кнопки удаления, которая будет использоваться один раз сразу после удаления, почему вы должны продолжать повторять цикл for. Просто используйте break после выполнения условия if
а мой способ может решить эту проблему или пользователи выше тоже давали полезные советы?
Я бы предложил вам поступить иначе: вместо на лету удаления элементов из массива сначала собрать элементы, которые нужно удалить, в другой массив, и только после цикла - удалить элементы.
@VladyslavMatviienko приведенный выше код предназначен для его кнопки удаления, которая присутствует во всех держателях просмотра ресайклера, поэтому нет необходимости собирать элементы, которые необходимо удалить.
Вы удалили элемент из исходного массива, поэтому вы получаете исключение, поэтому используйте новый массив для отфильтрованных значений.
Проблема в нижней строке
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 и добавьте в него все элементы массива. и новыйСписок.удалить(объект); и вы можете восстановить его на своем синглтоне после завершения цикла for
а как насчет возврата после удаления элемента массива? это может мне помочь? или объявление массива лучше?
да, я обновил ответ, теперь попробуйте с ним. for loop {был неуместен. теперь это сработает для вас
так это лучше, чем мое решение, которое я разместил ниже? ваше решение также работает хорошо, но почему оно лучше?
Я думаю, что да, потому что ваш код будет генерировать ошибку или сбой, когда у вас есть более одного элемента в вашем списке. потому что вы удалили элемент из массива внутри для . это нехорошо, потому что вы не должны выполнять операции чтения и записи в одном списке в цикле for
Просто добавьте оператор 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;
}
}
}
Причина, по которой вы получаете исключение после удаления первого элемента, заключается в том, что цикл выполняется после удаления первого элемента. цикл заканчивается ровно после удаления второго элемента.
Вы используете метод удаления внутри итерации цикла 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)
}
@AndrewGoroshko, какую ошибку вы получаете с приведенным выше кодом?
@AndrewGoroshko, извините, код был немного неуместен. Теперь попробуйте с фиксированным кодом.
Нумерация элементов в Java/Kotlin
0...length-1
поэтому, если размер вашего массива равен 10, вы можете получить из него 0...9 элементов. Проверьте своеfor (i in 0 until array.size()) {
состояние