英文:
Black screen and slow startup on starting app, when getting contact information into a RecyclerView?
问题
我在获取联系信息并放入RecyclerView时遇到了启动缓慢和黑屏的问题。当删除该进程时,问题消失了。以下是getContacts
函数的内容,如果有人能帮忙,谢谢...
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 = requireActivity().contentResolver.query(uri, null, null, null, sort)!!
// Check condition
if (cursor.count > 0) {
while (cursor.moveToNext()) {
val id: String = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID))
val name: String = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME))
val img: String = getPhotoUriFromID(id).toString()
val phoneUri: Uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI
val selection: String = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " =?"
// Initialize phone cursor
val phoneCursor: Cursor = requireActivity().contentResolver.query(phoneUri, null, selection,
arrayOf(id), null)!!
// 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()
}
}
英文:
I have a problem with a slow start and black screen when getting contact information into RecyclerView. And, the problem is gone when deleting the process. Below is the function of getContacts, if anyone can help. Thank you...
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 = requireActivity().contentResolver.query(uri, null, null, null, sort)!!
// Check condition
if (cursor.count > 0) {
while (cursor.moveToNext()) {
val id: String = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID))
val name: String = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME))
val img: String = getPhotoUriFromID(id).toString()
val phoneUri: Uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI
val selection: String = ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" =?"
// Initialize phone cursor
val phoneCursor: Cursor = requireActivity().contentResolver.query(phoneUri, null, selection,
arrayOf(id), null)!!
// 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()
}
}
答案1
得分: 2
你的代码中存在两个主要问题:
- 你很可能是在UI线程上运行上述查询,这会阻塞整个手机,直到查询完成加载,这对用户体验非常不好。
- 你的代码首先运行一个查询来获取所有联系人,然后对每个联系人运行更多的查询,这意味着如果你的用户有5000个联系人,你的代码将需要运行5000个查询,这可能需要很长时间才能完成。
要解决问题#1,你应该以异步方式调用你的代码,并在查询完成后更新你的RecyclerView,以在屏幕上加载你的项目。
有许多方法可以做到这一点,可以简单使用AsyncTask
,也可以更高级一些,如AsyncListUtil
。
以下是一些资源:
- https://androidwave.com/implementation-of-recyclerview-with-cursor-adapter/
- https://medium.com/android-news/how-to-use-asynclistutil-16b5175bb468
问题#2可以通过直接在ContactsContract.Data表上运行查询来解决,而不是在ContactsContract.Contacts表上运行查询。
Data表包含所有联系人的所有信息,因此你可以通过一个大查询获取所有需要的信息,这比多个较小的查询要快得多。
以下是如何做到这一点的示例:https://stackoverflow.com/a/52602698/819355
英文:
You have two major issues in your code:
- You're probably running the above queries on the UI thread which blocks the entire phone until the query finishes loading, which is really bad user-experience.
- Your code runs one query to fetch all contacts, and then more queries per contact, that means if your user has 5000 contacts your code will need to do 5000 queries which can take a long time to complete.
To fix issue #1, you should call your code asynchronously and update your RecyclerView when the query finishes to load your items on screen.
There are many ways to do this,
as simply as an AsyncTask
, and more advanced like AsyncListUtil
here are some resources:
- https://androidwave.com/implementation-of-recyclerview-with-cursor-adapter/
- https://medium.com/android-news/how-to-use-asynclistutil-16b5175bb468
Issue #2 can be fixed by running your query directly on the ContactsContract.Data table instead of the ContactsContract.Contacts table.
The Data table contains all information on all contacts, so you can get all your need in one big query which is much faster then multiple smaller queries.
Here's an example on how to do that: https://stackoverflow.com/a/52602698/819355
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论