使用 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 的适配器的主要内容,如果未能解决你的问题,请参考以下文章

读取游标

使用电话号码选择联系人而不是读取电话号码时出现问题

如何更快地读取android中的所有电话联系人?

在 Android 2.2 上读取联系人

使用 Intent.ACTION_PICK 读取电话号码和地址

在 Android 中从电话簿中读取联系人