我正在尝试从用户的通话记录中获取唯一的数字,并在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}
position
,id
,oldPos
,pLpos
等每次都不同,但错误基本相同。
我也尝试过编写日志,以确保在将元素添加到contacts
数组列表之前我没有尝试插入元素,但日志说一切都很好。
知道这里可能有什么问题吗?
答案 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