2

在我的应用程序中,我在列表视图中列出联系人。联系人数量为 1000+。我得到了联系方式

通过使用cr.query(...) 的ContentResolver 查询,将值存储在 arraylist 中

然后在 setListAdapter(...) 中加载数组列表。显示我的所有联系人

应用程序需要将近 1 分钟,因此我使用异步任务,但使用异步任务没有太大区别。

我需要在 2 到 4 秒内显示所有联系人。我签入了android 模拟器上的默认联系人应用程序,该应用程序在 2 到 4 秒内加载。 我花了

在谷歌很久了。但我找不到任何有用的解决方案。请帮助我如何快速加载列表视图上的联系人。请帮我。

我的编码示例:

    private ArrayList<ContactListEntry> loadContactListInternal(String searchString) {
        ArrayList<ContactListEntry> contactList = new ArrayList<ContactListEntry>();
    ContentResolver cr = getContentResolver();
    Cursor cur = null;
    String[] projection = new String[] {BaseColumns._ID,ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.Contacts.PHOTO_ID};
    ....
        cur=cr.query(ContactsContract.Contacts.CONTENT_URI, projection, selection, null, ContactsContract.Contacts.DISPLAY_NAME + " ASC");

    while (cur.moveToNext()) {
         int id = Integer.parseInt(cur.getString(0));
             ....   
        if (input !=null)
            photo = BitmapFactory.decodeStream(input);
         ....
        ArrayList<ContactListEntry.PhoneEntry> phoneEntries = new ArrayList<ContactListEntry.PhoneEntry>();

            String[] projection1 = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER,ContactsContract.CommonDataKinds.Phone.TYPE};    
            Cursor pcur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,projection1, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { String.valueOf(id) }, null);
            while (pcur.moveToNext()) {
                ...
            }
            pcur.close();

            ContactListEntry entry = new ContactListEntry(id, name, photo, phoneEntries);
            contactList.add(entry);
    }
    cur.close();

    return contactList;
}
    .....
    in another class
        private void selectionUpdated() {
                ....
         setListAdapter(new SelectedArrayAdapter(this, app.selectedContacts));
            ... 
       }
4

5 回答 5

1

所以你的问题是你为每个联系人做了很多子查询。我曾经有同样的问题。我的情况是我展示了很多联系人并允许用户点击其中的任何一个。之后,我开始在另一个活动中处理联系人。

那时我终于决定我应该只显示名称,然后在我启动下一个活动之前懒惰地获取所有其他数据。这太神奇了:我的程序速度几乎降低了 200 倍,并且操作对用户完全不可见。

如果我没记错的话,默认的 android 列表也是如此——它只显示名称,然后加载所有其他与联系人相关的数据。

于 2012-04-25T10:29:30.420 回答
1

我使用光标适配器,我剪切了数据库、数组适配器并优化了代码。

于 2012-05-25T12:13:29.210 回答
1

使用投影和选择参数的概念来检索我的案例中的联系人 500 个联系人,最初需要 12 秒。

现在需要 350 毫秒(不到一秒)

void getAllContacts() {
    long startnow;
    long endnow;

    startnow = android.os.SystemClock.uptimeMillis();
    ArrayList arrContacts = new ArrayList();

    Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
    String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER;
    Cursor cursor = ctx.getContentResolver().query(uri, new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER,   ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.Contacts._ID}, selection, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");

    cursor.moveToFirst();
    while (cursor.isAfterLast() == false) {

        String contactNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
        String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
        int phoneContactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
        int contactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID));
        Log.d("con ", "name " + contactName + " " + " PhoeContactID " + phoneContactID + "  ContactID " + contactID)

        cursor.moveToNext();
    }
    cursor.close();
    cursor = null;

    endnow = android.os.SystemClock.uptimeMillis();
    Log.d("END", "TimeForContacts " + (endnow - startnow) + " ms");
}

有关此链接的更多信息http://www.blazin.in/2016/02/loading-contacts-fast-from-android.html ....

于 2016-02-17T12:41:39.757 回答
0

考虑只使用一个查询并摆脱子查询的想法(如前所述)。您可以通过使用 Content Uri 进行查询来提高速度:

"ContactsContract.CommonDataKinds.Phone.CONTENT_URI"

此 URI 还具有“ContactsContract.Contacts.DISPLAY_NAME”字段。

您可能还想考虑执行此查询并在单独的线程中使用适配器以使其完全透明。

这对我有用。

于 2013-06-01T17:14:11.603 回答
0

优化的解决方案在这里......

private static final String[] PROJECTION = new String[] {
        ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
        ContactsContract.Contacts.DISPLAY_NAME,
        ContactsContract.CommonDataKinds.Phone.NUMBER
    };
.
.
.

ContentResolver cr = getContentResolver();
        Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null);
        if (cursor != null) {
            try {
                final int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
                final int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);

                String name, number;
                while (cursor.moveToNext()) {
                    name = cursor.getString(nameIndex);
                    number = cursor.getString(numberIndex);
                }
            } finally {
                cursor.close();
            }
        }

干杯...:)

于 2015-02-24T07:11:28.410 回答