【问题标题】:Android - How to fetch a contact name and number without using Cursors?Android - 如何在不使用光标的情况下获取联系人姓名和号码?
【发布时间】:2026-02-21 19:40:01
【问题描述】:

我的应用程序存在很大的性能问题。通过 traceview 后,我发现我的应用程序的大部分性能都被游标消耗了。所以我想知道是否有任何替代光标来处理设备联系人列表。如果别无选择,请告诉我如何处理光标,以免拖慢您的应用程序。

请帮忙!!

谢谢。

我的这部分代码有性能问题:-

public void getDisplayName()
{       
    Cursor c1 = this.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

    String personName = null, number = null;
    try 
    {
        Log.e(TAG, "I am here!!");
        if(c1.getCount() > 0)
        {
            Log.e(TAG, "I am here2!!");
            while(c1.moveToNext())
            {
                HashMap<String,String> item = new HashMap<String,String>();
                String id = c1.getString(c1.getColumnIndex(Contacts._ID));
                personName = c1.getString(c1.getColumnIndex(Contacts.DISPLAY_NAME));
                item.put("Name", personName);
                Cursor cur = this.getContentResolver().query(CommonDataKinds.Phone.CONTENT_URI, null, CommonDataKinds.Phone.CONTACT_ID +" = ?", new String[]{id}, null);
                while(cur.moveToNext())
                {
                    Log.e(TAG, "I am here!!3");
                    number = cur.getString(cur.getColumnIndex(CommonDataKinds.Phone.NUMBER));
                    item.put("Number", number);
                }
                displayName.add(item);          
            }
        }
    }
    finally
    {
        c1.close();
    }
}

【问题讨论】:

  • 据我所知,没有其他好方法可以做到这一点。不过,我还没有遇到游标的性能问题。也许那里有一些不必要的代码?贴出来,说不定有人会发现问题。
  • 向我们展示代码段落,您找到了性能问题。

标签: android performance cursor


【解决方案1】:

如何在不使用光标的情况下获取联系人姓名和号码?

这是不可能的。

我的应用存在很大的性能问题。

您使用 N+1 个查询而不是使用单个查询,其中 N 是另一个查询返回的行数。与仅执行单个查询相比,这保证会给您带来较差的性能。

您可以获取用户的姓名和_ID以及电话号码:

    String[] PROJECTION=new String[] { Contacts._ID,
                                        Contacts.DISPLAY_NAME,
                                        Phone.NUMBER
                                        };
    Cursor c=a.managedQuery(Phone.CONTENT_URI, PROJECTION, null, null, null);

另外,永远不要在循环中调用getColumnIndex(),因为值永远不会改变。

【讨论】:

  • @CommonsWare:如果我想要 display_name、数字 + 电子邮件。什么是最好的查询?我不知道什么查询可以得到这两个。并且不确定如何使用光标连接器。如果你能给我一个方向,那就太好了。目前,我得到 contact_id 并创建 2 个光标来查找号码和电子邮件。所以性能很差[我的问题] (*.com/questions/10811801/…)
【解决方案2】:

我正在处理相同的代码,并且在第一种方法中我需要电子邮件和电话号码获取 612 个联系人大约需要 35 秒,当我优化它时,获取 612 个联系人需要 2 秒

我的代码。

ContentResolver cr = context.getContentResolver();

    String[] projection = new String[] { Contacts.DISPLAY_NAME, Phone.NUMBER };

    String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = ?";
    String[] selectionArgs = { String.valueOf(1) };

    Cursor cur = cr.query(Phone.CONTENT_URI, projection, selection, selectionArgs, null);

    if (cur.getCount() > 0) {
        while (cur.moveToNext()) {
            String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
            String phNo = cur.getString(cur.getColumnIndex(Phone.NUMBER));
            ContactModel contactModel = new ContactModel();
            contactModel.setName(name);
            contactModel.setPhoneNumber(phNo);
            contactList.add(contactModel);
        }
    }

    String[] projectionEmail = new String[] { Contacts.DISPLAY_NAME, Email.ADDRESS };

    String selectionEmail = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = ?";
    String[] selectionArgsEmail = { String.valueOf(1) };

    Cursor curEmail = cr.query(Email.CONTENT_URI, projectionEmail, selectionEmail, selectionArgsEmail, null);

    if (curEmail.getCount() > 0) {
        while (curEmail.moveToNext()) {
            String Emailname = curEmail.getString(curEmail.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
            String email = curEmail.getString(curEmail.getColumnIndex(Email.ADDRESS));
            ContactModel contactModel = new ContactModel();
            contactModel.setName(Emailname);
            contactModel.setEmailId(email);
            contactList.add(contactModel);
        }
    }

`

【讨论】:

    最近更新 更多