如何在android上的listview中加快联系人的加载速度

时间:2012-04-25 10:12:44

标签: android android-listview android-contacts

在我的应用中,我在列表视图中列出了联系人。没有联系人是1000+。我得到了联系方式

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

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

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

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

谷歌很长一段时间。但我无法得到任何有用的解决方案。请帮我看看如何快速加载listview上的联系人。请帮我。

我的编码样本:

    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));
            ... 
       }

5 个答案:

答案 0 :(得分:1)

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

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

如果我没有错,默认的android列表也会这样做 - 它只显示名称,稍后会加载所有其他与联系人相关的数据。

答案 1 :(得分:1)

我使用游标适配器,我剪切数据库,arrayadapter并优化代码。

答案 2 :(得分: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 ....

答案 3 :(得分:0)

考虑只有一个查询并摆脱子查询的想法(如已经建议的那样)。只需使用Content Uri查询即可实现速度:

"ContactsContract.CommonDataKinds.Phone.CONTENT_URI"

此URI还包含“ContactsContract.Contacts.DISPLAY_NAME”字段。

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

这对我有用。

答案 4 :(得分: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();
            }
        }

干杯...:)