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

Posted

技术标签:

【中文标题】如何在android上的listview中快速加载联系人【英文标题】:How to fast the contacts loading in listview on android 【发布时间】:2012-05-06 00:22:53 【问题描述】:

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

通过使用 ContentResolver 查询,即 cr.query(...),将值存储在数组列表中

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

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

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

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

我的编码示例:

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

【问题讨论】:

您究竟在列表视图中显示什么? 我用右侧的复选框显示联系人姓名和电话号码,并为下一个过程存储其他值。 这是我们尝试提高性能的另一个线程:***.com/questions/9546047/…。正如你再次看到的那样,我是唯一一个敢于回答的人。 OP 没有找到任何更清洁的解决方案 【参考方案1】:

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

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

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

【讨论】:

是的,我使用两个查询来获取详细信息,在第一个查询中我得到 id、name...,在第二个查询中我将联系人 ID 作为参数传递以获取电话号码和类型。但是需要两个查询(即子查询)来获取电话号码和此类详细信息。有什么方法可以组合成一个查询或单个查询来获取所有详细信息?请询问我的问题。 @murali_ma 您不使用两个查询。您使用 n + 1 查询,其中 n 是电话中的联系人数量。我会对此进行更多搜索,但是当时我尝试按照您的想法做同样的事情,但徒劳无功。【参考方案2】:

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

【讨论】:

你能解释一下,我有同样的问题。我目前正在使用数组适配器。 @Vikas Rana,我的数据在游标(数据库)中,所以我使用了游标适配器,在你的情况下,你在 arraylist 中有多少数据? 我在数组列表中添加电话号码、姓名和联系人照片而不将其存储到数据库中 你能解释一下怎么做吗?【参考方案3】:

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

现在需要 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 ....

【讨论】:

【参考方案4】:

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

"ContactsContract.CommonDataKinds.Phone.CONTENT_URI"

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

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

这对我有用。

【讨论】:

【参考方案5】:

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

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();
            
        

干杯...:)

【讨论】:

以上是关于如何在android上的listview中快速加载联系人的主要内容,如果未能解决你的问题,请参考以下文章

具有快速滚动和字母部分索引的 Android ListView

Android中ListView异步加载图片错位重复闪烁问题分析及解决方案

如何在 Android 的 ListView 中延迟加载图像

在android listview中使用onScroll

Android:如何像在联系人应用程序中一样使用字母索引器和快速滚动填充 ListView。

Android:如何在listView上的项目中结合滑动手势和长按