如何使用 CommonDataKinds.Phone 内部查询使此 ContactsContract.Contact 查询更快?

Posted

技术标签:

【中文标题】如何使用 CommonDataKinds.Phone 内部查询使此 ContactsContract.Contact 查询更快?【英文标题】:How can I make this ContactsContract.Contact query faster with CommonDataKinds.Phone inner query? 【发布时间】:2017-01-20 17:36:11 【问题描述】:

我正在遍历Contacts 表,每次迭代都在Phone 表上进行迭代,所以它需要appx。 4 秒完成 243 个联系人的联系人列表(无需迭代它立即加载的电话号码)。我确信有办法让它更快。

已经做出预测以仅获取所需的列,但没有太大改进。也许我应该改进 SQLite 查询或以其他方式迭代:

Contact realmContact = new Contact();

        Uri uri = Contacts.CONTENT_URI;

        String[] projection = 
                Contacts.LOOKUP_KEY,
                Contacts.DISPLAY_NAME_PRIMARY,
                Contacts.LAST_TIME_CONTACTED,
                Contacts.HAS_PHONE_NUMBER
        ;

        String selection = "((" + CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + " NOTNULL) AND ("
                + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
                + CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + " != '' ))";

        Cursor phones = getActivity()
                .getContentResolver()
                .query(uri, projection, selection, null, null);

        while (phones.moveToNext()) 
            String id = phones.getString(phones.getColumnIndex(Contacts.LOOKUP_KEY));

            String name = phones.getString(phones.getColumnIndex(Contacts.DISPLAY_NAME_PRIMARY));

            String lastTimeContacted = phones.getString(phones.getColumnIndex(Contacts.LAST_TIME_CONTACTED));
            long data = Long.parseLong(lastTimeContacted);
            String date = new SimpleDateFormat("dd/MM/yyyy | HH:mm").format(new Date(data));

            if (Integer.parseInt(phones.getString(phones.getColumnIndex(Contacts.HAS_PHONE_NUMBER))) > 0) 
                Cursor pCur = getActivity().getContentResolver().query(
                        CommonDataKinds.Phone.CONTENT_URI,
                        new String[]CommonDataKinds.Phone.NUMBER,
                        CommonDataKinds.Phone.LOOKUP_KEY + " = ?",
                        new String[]id, null);

                int iterationCounter = 0;
                String phoneNumber = "";
                while (pCur.moveToNext()) 
                    phoneNumber += iterationCounter == 0 ?
                            pCur.getString(pCur.getColumnIndex(CommonDataKinds.Phone.NUMBER))
                             : "," + pCur.getString(pCur.getColumnIndex(CommonDataKinds.Phone.NUMBER));

                    iterationCounter += 1;
                
                realmContact.setNumber(phoneNumber);
                Log.i("asd-number", phoneNumber);
                pCur.close();
            
            realmContact.setId(id);
            realmContact.setName(name);
            realmContact.setLastTimeContacted(
                    getActivity().getResources()
                            .getString(R.string.contacts_list_fragment_last_call)
                            + date);
            realmContact.setIsBeingSaved(true);
            _realm.insertOrUpdate(realmContact);

【问题讨论】:

只需在光标上迭代CommonDataKinds.Phone.CONTENT_URI 他们没有display_name 是的,他们有:ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME @pskink 如果联系人有多个号码,我会在列表中获得该数量的联系人重复项。有什么方法可以一口搞定一个联系人的所有号码? 【参考方案1】:

正如 @pskink 在 cmets 中提到的,您需要查询 Phone 表。 要按联系人获取电话列表,您可以维护一个从contactIdList 的电话的HashMap

这里有一个小 sn-p 可能会有所帮助(您可能需要稍微调整一下集合,以便每个联系人只存储一次显示名称):

HashMap<Long, ArrayList<String>> phones = new HashMap<Long, ArrayList<String>>();
String[] projection = new String[]  Phone.CONTACT_ID, Phone.DISPLAY_NAME, Phone.NUMBER ;
Cursor c = cr.query(Phone.CONTENT_URI, projection, null, null, null);
while (c != null && c.moveToNext()) 
    long contactId = c.getLong(0);
    ArrayList<String> list = phones.get(contactId);
    if (list == null) 
        ArrayList<String> list = new ArrayList<String>();
        phones.put(contactId, list);
    
    list.add(c.getString(1) + " " + c.getString(2));

【讨论】:

以上是关于如何使用 CommonDataKinds.Phone 内部查询使此 ContactsContract.Contact 查询更快?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]

如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?

如何使用laravel保存所有行数据每个行名或相等

如何使用 Math.Net 连接矩阵。如何使用 Math.Net 调用特定的行或列?

WSARecv 如何使用 lpOverlapped?如何手动发出事件信号?