Android kotlin - сбой приложения RecyclerView после удаления элементов в определенном порядке - PullRequest
0 голосов
/ 02 ноября 2018

Это адаптер:

class ContactsAdapter(val context: Context, private val users: MutableList<Contacts>, val itemClick: (Contacts) -> Unit) : RecyclerView.Adapter<ContactsAdapter.ViewHolder>(){

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {

        holder.remove.setOnClickListener {

            val builder = AlertDialog.Builder(context)
            builder.setMessage(R.string.delete_contact)

            builder.setPositiveButton(R.string.yes){_, _ ->
                users.removeAt(position)
                notifyItemRemoved(position)
            }

            builder.setNegativeButton(R.string.no){_,_ ->

            }

            val dialog: AlertDialog = builder.create()
            dialog.show()
        }
    }

    override fun getItemCount() = users.size

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.contacts, parent, false)
        return ViewHolder(view, itemClick)
    }

    class ViewHolder(itemView: View?, val itemClick: (Contacts) -> Unit) : RecyclerView.ViewHolder(itemView!!){
        val remove = itemView!!.removecontact!!
    }
}

У меня есть 2 элемента для тестирования, когда я удаляю второй, затем первый, все нормально, но когда сначала, а затем второй, приложение вылетает, и ошибка:

java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
        at java.util.ArrayList.remove(ArrayList.java:503)
        at com.xxx.xxx.classes.ContactsAdapter$onBindViewHolder$2$1.onClick(ContactsAdapter.kt:57)
        at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:177)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6944)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

В чем может быть проблема?

Заранее спасибо

Ответы [ 3 ]

0 голосов
/ 02 ноября 2018

У меня есть 2 элемента для тестирования, когда я удаляю второй, затем первый, все нормально, но когда сначала, а затем второй, приложение вылетает.

Полагаю, вы не обновляете значения в списке. Когда вы удаляете свой первый элемент, все в порядке, вы удаляете Индекс 0 из списка 2 Но ваш второй сбой, потому что вы пытаетесь удалить Индекс 1 (второй элемент) из списка, в котором остался только один элемент.

ваш "notifyItemRemoved (position)" должен переназначить индусы всех элементов, оставшихся после удаления одного

0 голосов
/ 02 ноября 2018

Во-первых, установите прослушиватель щелчков вне держателя bindview, так как это плохая практика. Просто установите его на onCreateViewHolder. Затем вы узнаете, что слушатель вызывается впервые, как только адаптер настроен. Для этого вам нужно остановить вызов, просто объявив переменную bool и присвоив ей значение false в классе адаптера следующим образом.

 private var islistenerCalledFirst: Boolean = false;

Затем в OnCreateViewHolder установите слушателя. Обратите внимание, что вы можете получить позицию элемента, вызвав viewHolder.getAdapterPosition ().

  holder.remove.setOnClickListener {

        if(islistenerCalledFirst){
              ... //your logic
        }

        islistenerCalledFirst = true
    }

Надеюсь, это работает для вас.

0 голосов
/ 02 ноября 2018

Как видите, это IndexOutOfBoundsException, потому что вы пытаетесь получить доступ к индексу 1 в массиве размера 1. Это в основном потому, что вы напрямую используете аргумент position из onBindViewHolder изнутри setPositiveButton вызов AlertDialog.

Вместо этого используйте метод holder.getAdapterPosition, чтобы получить последнюю позицию. Это должно предотвратить аварию.

Редактировать # 1 : Я имею в виду замену использования position на holder.getAdapterPosition(). Ваш onBindViewHolder должен выглядеть следующим образом после правок:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {

    holder.remove.setOnClickListener {

        val builder = AlertDialog.Builder(context)
        builder.setMessage(R.string.delete_contact)

        builder.setPositiveButton(R.string.yes){_, _ ->
            users.removeAt(holder.getAdapterPosition())
            notifyItemRemoved(holder.getAdapterPosition())
        }

        builder.setNegativeButton(R.string.no){_,_ ->

        }

        val dialog: AlertDialog = builder.create()
        dialog.show()
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...