使用 ContactsContract 获取联系人的最佳方式

The best way to get contacts by using ContactsContract

我正在尝试获取在我的电话簿中可见的联系人。假设有 5 个联系人的号码保存在我的设备中,3 个联系人的号码保存在我的 Gmail 帐户中。此外,请考虑设备联系人跨越 Gmail 联系人。以下方法输出所有 8 个联系人:

public void getContactList() {
    contactList.clear();

    Cursor phones = null;

    try {
        phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
        while (phones.moveToNext())
        {
            String _name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            String _number = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

            HashMap<String , String> contactMap= new HashMap<String, String>();

            contactMap.put("NAME", _name);
            contactMap.put("NUMBER", _number);

            contactList.add(contactMap);
            numbers.add("+" + _number);
            Log.v("" + counter++, _number + " " + _name);
        }
        phones.close();

    } catch ( Exception e ) {
        // TODO: handle exception
    }
    finally {
        if(phones != null){
            phones.close();
        }
    }
}

但是,在类似的问题中,人们建议使用以下方法。此方法输出 64 行。换句话说,无论第一种方法是什么,它都会循环 8 次 returns:

public void getContactList() {
    contactList.clear();

    String phoneNum[] = null;
    Cursor cur = null;
    Cursor pCur = null;
    try {
        ContentResolver cr = getContentResolver();
        cur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
        int i = 0;

        if (cur.getCount() > 0) {

            phoneNum = new String[cur.getCount()];

            while (cur.moveToNext()) {
                String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
                String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

                if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
                    // get the phone number
                    pCur = cr.query(
                            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                            null,
                            null,
                            null,
                            ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");

                    while (pCur.moveToNext()) {
                        // int _id = i;
                        String _name = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                        String _number = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                        _number = _number.replaceAll("[\D]", "");

                        HashMap<String , String> contactMap= new HashMap<String, String>();

                        contactMap.put("NAME", _name);
                        contactMap.put("NUMBER", _number);

                        contactList.add(contactMap);
                        phoneNum[i] = _number;

                        Log.v("" + counter++, _number + " " + _name);
                    }
                    pCur.close();
                }
                i++;
            }
        }
        cur.close();
    } catch ( Exception e ) {
        // TODO: handle exception
    }
    finally {
        if(pCur != null){
            pCur.close();
        }
        if(cur != null){
            cur.close();
        }
    }
}

如果有人建议第二种方法,他们应该考虑我没有注意到的一点。但是,我还没有找到那一点。当然,我无意无缘无故地再循环我的联系人七次。为什么人们说第二种方法更好?这是做什么人情或者验证?

如果您只想要所有可见联系人中的 DISPLAY_NAME 和 PHONE_NUMBER,您的方法是完美的。

当您想要将联系人的多个 phone 号码分组到单个数据结构中时,第二种方法很有用,但您错过的是第二个查询也应该将联系人 ID 作为过滤器,否则您只是查询所有联系人的所有 phone 号码,而不是查询单个联系人的所有 phone 号码。