获取联系人的数据到 RecyclerView 需要很长时间

问题描述 投票:0回答:1

我正在尝试获取联系人的数据(姓名、号码和照片 URI),但速度太慢,在查看 UI 之前显示黑屏几秒钟。当尝试在单独的线程中执行此操作时,以下错误似乎将进程移至主线程。如果有人可以帮助解决这个问题, 谢谢...

  • android.view.ViewRootImpl$CalledFromWrongThreadException: 只有创建视图层次结构的原始线程才能触及它的视图
private fun checkPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) !=
            PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_CONTACTS), 100)
        } else {
            getContactList()
        }
    }

private fun getContactList() {
        val uri: Uri = ContactsContract.Contacts.CONTENT_URI
        // Sort by ascending
        val sort: String = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" ASC"
        // Initialize Cursor
        val cursor: Cursor = this.contentResolver.query(uri, null, null, null, sort)!!
        // Check condition
        if (cursor.count > 0) {
            while (cursor.moveToNext()) {
                val name: String = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Data.DISPLAY_NAME))
                val img = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.PHOTO_URI))
                val phoneUri: Uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI
                // Initialize phone cursor
                val phoneCursor: Cursor = this.contentResolver.query(phoneUri,
                    null, null, null, sort)!!
                // Check condition
                if (phoneCursor.moveToNext()) {
                    val number: String = phoneCursor.getString(phoneCursor
                        .getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER))
                    // Initialize Contact Model
                    val model = ContactModel(name, number, img)
                    contactArr.add(model)
                    groupListAdapter.notifyDataSetChanged()
                    // Close Phone Cursor
                    phoneCursor.close()
                }
            }
            // Close Cursor
            cursor.close()
        }
    }
lifecycleScope.launch { checkPermission() }
android kotlin android-recyclerview kotlin-coroutines android-contacts
1个回答
0
投票

您正在尝试更新每个项目的整个适配器。将所有内容收集到列表中然后更新适配器会更有意义。

您可以在 IO 调度程序上运行大部分工作,以防加载联系人需要一段时间,并使用 Main 调度程序触摸视图。您可以使用

withContext
.

切换调度员

您也无法在所有条件下关闭游标——您是在 if 语句中执行此操作,因此如果条件为假,则您正在泄漏游标。

修复了上述问题的函数版本:

private fun getContactList() = lifecycleScope.launch(Dispatchers.IO) {
    val uri: Uri = ContactsContract.Contacts.CONTENT_URI

    // Sort by ascending
    val sort: String = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" ASC"

    val cursor: Cursor = this.contentResolver.query(uri, null, null, null, sort)
        ?.takeIf { it.count > 0) ?: run { 
            Log.w(TAG, "No contracts returned.")
            return@launch
        }

    while (cursor.moveToNext()) {
        val name: String = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Data.DISPLAY_NAME))
        val img = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.PHOTO_URI))
        val phoneUri: Uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI

        val phoneCursor: Cursor = this.contentResolver.query(phoneUri, null, null, null, sort)

        if (phoneCursor != null && phoneCursor.moveToNext()) {
            val number: String = phoneCursor.getString(phoneCursor
                    .getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER))

            val model = ContactModel(name, number, img)
            contactArr.add(model)
        }
        phoneCursor?.close()
    }

    cursor.close()
    withContext(Dispatchers.Main) { groupListAdapter.notifyDataSetChanged() }
}
© www.soinside.com 2019 - 2024. All rights reserved.