Android中如何使用AsyncTask读取手机通讯录联系人
Android AsyncTask 通讯录读取优化实现方案
注:AsyncTask 自 Android 11(API 30)开始被官方标记为废弃,若适配高版本系统优先考虑协程、WorkManager 等方案,以下实现适用于低版本兼容场景
1. 前置权限配置
首先在 AndroidManifest.xml 中声明通讯录读取权限:
<uses-permission android:name="android.permission.READ_CONTACTS" />
Android 6.0 及以上版本需要在启动读取任务前,动态申请 READ_CONTACTS 权限,权限校验通过后再执行后续操作。
2. 自定义通讯录读取 AsyncTask 类
首先定义通讯录实体类存储读取结果,再继承 AsyncTask 实现耗时逻辑:
// 通讯录实体类,自行补充构造、getter、setter 方法 public class ContactInfo { private String name; private String phone; } // 异步读取任务类 public class ReadContactsTask extends AsyncTask<Void, Void, List<ContactInfo>> { private Context appContext; private OnContactsReadListener readListener; // 构造方法传入上下文和结果回调,用ApplicationContext避免内存泄漏 public ReadContactsTask(Context context, OnContactsReadListener listener) { this.appContext = context.getApplicationContext(); this.readListener = listener; } // 后台线程执行耗时的通讯录查询逻辑 @Override protected List<ContactInfo> doInBackground(Void... voids) { List<ContactInfo> resultList = new ArrayList<>(); ContentResolver resolver = appContext.getContentResolver(); // 查询通讯录数据 Cursor cursor = resolver.query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC" ); if (cursor != null) { while (cursor.moveToNext()) { String name = cursor.getString(cursor.getColumnIndexOrThrow( ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); String phone = cursor.getString(cursor.getColumnIndexOrThrow( ContactsContract.CommonDataKinds.Phone.NUMBER)); resultList.add(new ContactInfo(name, phone)); } cursor.close(); } return resultList; } // 任务完成后回调,运行在主线程可直接更新UI @Override protected void onPostExecute(List<ContactInfo> contactInfos) { super.onPostExecute(contactInfos); if (readListener != null) { readListener.onReadSuccess(contactInfos); } } // 结果回调接口 public interface OnContactsReadListener { void onReadSuccess(List<ContactInfo> contactList); } }
3. 页面调用异步任务
权限申请通过后,直接启动任务即可:
// 确认已获取READ_CONTACTS权限后执行 new ReadContactsTask(this, new ReadContactsTask.OnContactsReadListener() { @Override public void onReadSuccess(List<ContactInfo> contactList) { // 此处可直接使用读取结果更新列表、渲染UI } }).execute();
注意事项
- 若页面销毁时不需要接收读取结果,可在
onDestroy()生命周期中调用task.cancel(true)终止任务,避免内存泄漏 - 通讯录查询逻辑和你原有同步读取逻辑保持一致即可,仅需要把耗时逻辑移动到
doInBackground方法中执行
内容的提问来源于stack exchange,提问作者Abdul Rasheed
相关产品推荐
相关产品推荐

