如何加速Android/Kotlin中通讯录邮箱地址的采集?
优化Android通讯录邮箱获取速度的方案
你的代码速度慢的核心原因是N+1查询问题:先查询所有联系人(1次),再为每个联系人单独查询邮箱(N次),大量重复的ContentResolver查询会严重拖慢执行效率。
直接查询ContactsContract.CommonDataKinds.Email.CONTENT_URI就能一次性获取所有邮箱地址,无需先查询联系人表——因为邮箱数据表本身就关联了联系人ID,且我们只需要邮箱地址字段,完全不需要依赖联系人表的前置查询。
优化后的代码:
fun getAllEmails(contentResolver: ContentResolver): String { val emailList = mutableListOf<String>() // 只声明需要的字段,减少数据传输量 val projection = arrayOf(ContactsContract.CommonDataKinds.Email.ADDRESS) try { contentResolver.query( ContactsContract.CommonDataKinds.Email.CONTENT_URI, projection, null, null, null )?.use { cursor -> val emailColumnIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS) while (cursor.moveToNext()) { // 过滤空邮箱地址,避免无效数据 cursor.getString(emailColumnIndex)?.let { email -> emailList.add(email) } } } return emailList.joinToString(",") } catch (e: Exception) { e.printStackTrace() return "" } }
核心优化细节:
- 单次查询替代N+1查询:直接从邮箱数据表拉取全部数据,彻底避免多次ContentResolver交互的开销
- 精准投影字段:只查询
ADDRESS字段,不返回无关列,减少内存占用和数据读取时间 - 空值过滤:通过
?.let跳过可能的空邮箱地址,避免无效数据加入结果集
如果后续需要关联联系人其他信息(如姓名),也可以在单次查询中完成,只需把对应字段(比如ContactsContract.CommonDataKinds.Email.DISPLAY_NAME)加入投影数组即可,无需额外发起查询。
内容的提问来源于stack exchange,提问作者Roger Smith
相关产品推荐
相关产品推荐

