使用 Async Task 读取电话联系人并将其设置为 AutoCompleteTextView 的适配器
Posted
技术标签:
【中文标题】使用 Async Task 读取电话联系人并将其设置为 AutoCompleteTextView 的适配器【英文标题】:Using Async Task to read the phone contacts and set them to an adapter for AutoCompleteTextView 【发布时间】:2018-06-07 02:59:05 【问题描述】:我已从设备读取所有电话联系人并将它们设置为 AutoCompleteTextView 的适配器。执行此操作的函数是:
private void storeContactsToArrayList()
Log.d("In ", "storeContactsToArrayList() called");
List<Contact> contactList = new ArrayList<>();
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if ((cur != null ? cur.getCount() : 0) > 0)
while (cur != null && cur.moveToNext())
String id = cur.getString(
cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(cur.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME));
if (cur.getInt(cur.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0)
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]id, null);
while (pCur.moveToNext())
String phoneNo = pCur.getString(pCur.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
// Log.i("GOT", "Name: " + name);
// Log.i("GOT", "Phone Number: " + phoneNo); //working
//To our POJO
Contact contact = new Contact();
contact.setName(name);
contact.setPhoneNumber(phoneNo);
contactList.add(contact);
pCur.close();
ArrayAdapter<Contact> contactsArrayAdapter =
new ArrayAdapter<Contact>(this, android.R.layout.simple_list_item_1, contactList);
//setting this adapter to our autocompleteTextView userInput
userInput.setAdapter(contactsArrayAdapter);
if(cur!=null)
cur.close();
但是,当我运行代码时,我意识到该函数需要相当长的时间才能执行,这似乎很糟糕。
据我所知,我应该使用像AdapterTask extends Async Task
这样的内部类来做同样的事情,但异步进行而不阻塞我的主 UI 线程。我试过这样做,但我做不到。
请建议我是否有任何其他方法可以在不使用 AsyncTask 的情况下做同样的事情,或者如果 AsyncTask 是要走的路,我怎样才能使用 AsyncTask 实现上述功能正在做的事情。
谢谢。
【问题讨论】:
参见this - 在rawQuery
内,您应该使用CommonDataKinds.Phone#CONTENT_FILTER_URI
(或PhoneLookup#CONTENT_FILTER_URI
)
【参考方案1】:
为后台任务创建一个单独的类并与侦听器(和接口)进行通信。下面是示例根据您的需要修改它。
public class FetchContacts extends AsyncTask<Void, Void, List>
private Context activity;
private OnContactFetchListener listener;
public FetchContacts(Context context, OnContactFetchListener listener)
activity = context;
this.listener = listener;
@Override
protected List doInBackground(Void... params)
List<Contact> contactList = new ArrayList<>();
// get Contacts here
return contactList;
@Override
protected void onPostExecute(List list)
super.onPostExecute(list);
if(listener!=null)
listener.onContactFetch(list);
public interface OnContactFetchListener
void onContactFetch(List list);
可以调用为 .
new FetchContacts(activity, new FetchContacts.OnContactFetchListener()
@Override
public void onContactFetch(List contacts)
// Here you will get the contacts
).execute();
【讨论】:
谢谢,我将在doInBackground()
中传递什么参数,我尝试通过将光标作为参数传递来这样做,但它不允许我调用 cursorObject.moveToNext()
或光标对象上的任何其他方法。
在这种情况下不需要在doInBackground()
中传递任何参数。只需将所有代码粘贴到 doInBackground()
中并返回 contactList
。
嘿,非常感谢,我按照你的建议做了,现在应用程序似乎打开得更快了,而不会像之前那样阻塞主 UI 线程。谢谢。
不能投票,但我接受了。非常感谢【参考方案2】:
就像@ADM 建议的那样。创建一个单独的类,而不是内部类。 FetchContacts.java
public class FetchContacts extends AsyncTask<Void, Void, List>
private Context activity;
private OnContactFetchListener listener;
public FetchContacts(Context context, OnContactFetchListener listener)
activity = context;
this.listener = listener;
@Override
protected List doInBackground(Void... voids)
List<Contact> contactList = new ArrayList<>();
// get Contacts here
ContentResolver cr = activity.getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if ((cur != null ? cur.getCount() : 0) > 0)
while (cur != null && cur.moveToNext())
String id = cur.getString(
cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(cur.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME));
if (cur.getInt(cur.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0)
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]id, null);
while (pCur.moveToNext())
String phoneNo = pCur.getString(pCur.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
// Log.i("GOT", "Name: " + name);
// Log.i("GOT", "Phone Number: " + phoneNo); //working
//To our POJO
Contact contact = new Contact();
contact.setName(name);
contact.setPhoneNumber(phoneNo);
contactList.add(contact);
pCur.close();
if (cur != null)
cur.close();
return contactList;
@Override
protected void onPostExecute(List list)
super.onPostExecute(list);
if (listener != null)
listener.onContactFetch(list);
public interface OnContactFetchListener
void onContactFetch(List list);
并调用该类,将联系人列表设置为 ArrayAdapter 并将 arrayadapter 设置为自动完成文本视图:
new FetchContacts(MainActivity.this, new FetchContacts.OnContactFetchListener()
@Override
public void onContactFetch(List contacts)
// Here you will get the contacts
ArrayAdapter<Contact> contactArrayAdapter = new ArrayAdapter<Contact>(MainActivity.this,
android.R.layout.simple_list_item_1, contacts);
userInput.setAdapter(contactArrayAdapter); //userInput is our AutoCompleteTextView
).execute();
【讨论】:
以上是关于使用 Async Task 读取电话联系人并将其设置为 AutoCompleteTextView 的适配器的主要内容,如果未能解决你的问题,请参考以下文章