在尝试插入多个项目并通知适配器时,RecyclerView抛出IndexOutOfBoundsException

时间:2018-02-22 12:43:41

标签: java android android-recyclerview kotlin recycler-adapter

我正在尝试从用户的通话记录中获取唯一的数字,并在RecyclerView中显示它们。通过唯一我的意思是,如果我在列表中显示了数字或相应的联系人,我必须跳过该项目。我希望使用Cursor来显示这一点,以便快速渲染。

为此,我实施了一个RecyclerView适配器,如下所示(仅显示相关代码, kotlin

class CallAdapter(val activity: Activity, var cursor: Cursor) : RecyclerView.Adapter<CallAdapter.ViewHolder>() {


        val handler = Handler()
        val contacts = ArrayList<Contact>()

        init {
            cursor.moveToFirst()
            UniqueLogs(this).start()
        }

        companion object {
            const val TAG = "CallAdapter"
        }

        override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
            val inflater = LayoutInflater.from(activity)
            val binding = CallLogItemBinding.inflate(inflater, parent, false)
            return ViewHolder(binding)
        }

        override fun getItemCount(): Int {
            return contacts.count()
        }

        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            val contact = contacts[position]

            ...

            cursor.moveToNext()
        }

        class ViewHolder(val binding: CallLogItemBinding) : RecyclerView.ViewHolder(binding.root)

        class UniqueLogs(val adapter: CallLogAdapterShobhit) : Thread() {
            private var available = true
            private val cursor = adapter.cursor
            private val hash: HashMap<String, Int> = HashMap<String, Int>()
            private val contacts = adapter.contacts
            private var count = 0

            override fun run() {
                cursor.moveToFirst()
                while (available && cursor.moveToNext()) {
                    var contact = adapter.getCurrentItemContact()

                    while (available && hash[contact.phoneNumber] == 1) {
                        if (cursor.moveToNext()) {
                            contact = adapter.getCurrentItemContact()
                        } else {
                            available = false
                        }
                    }

                    if (available) {
                        contacts.add(contact)
                        val position = count
                        count += 1

                        adapter.handler.post({
                            Log.d(TAG, "Position: $position Size: ${adapter.itemCount}")
                            adapter.notifyItemInserted(position)
                        })

                        hash[contact.phoneNumber] = 1
                    }
                }

            }
        }
    }

当我运行此代码时,我得到一个如下所示的异常: -

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{c75176c position=5 id=-1, oldPos=4, pLpos:4 scrap [attachedScrap] tmpDetached not recyclable(1) no parent}

positionidoldPospLpos等每次都不同,但错误基本相同。

我也尝试过编写日志,以确保在将元素添加到contacts数组列表之前我没有尝试插入元素,但日志说一切都很好。

知道这里可能有什么问题吗?

2 个答案:

答案 0 :(得分:0)

您正在后台线程中更新数据,但通知主线程。通知发生时,您可能进一步更改了数据。我建议您在后台进行所有更新,然后在完成所有操作后执行通用notifyDataSetChanged

另一种选择是在后台线程中计算整个新列表,然后更新实际数据并在主线程中通知。

答案 1 :(得分:0)

修改数据并同步调用$dbemails = "name@email.com,name@email.com,name@email.com"; // Fetched $dbemailsrp = str_replace(",", "', '", $dbemails); // Replace , with ', ' $dbemailscp = "'".$dbemailsrp."'"; // Add front and back ' $email = array($dbemailscp); // Doesn't work ,否则您将获得不一致的数据。

notifyItemInserted之前放置contacts.add(contact)应该解决它。

notifyItemInserted