【问题标题】:Android slow performance for getting contact's detailsAndroid 获取联系人详细信息的性能缓慢
【发布时间】:2016-06-15 23:35:22
【问题描述】:

我想显示包含电话号码但所有已分配号码的联系人。我想提高性能。有没有更有效的方法来做到这一点?喜欢一次获取所有联系人缩略图?这个 approach 对我来说失败了,因为光标不是空的,而是返回 empty(?) uri。

我已经进行了一些时间跟踪,看起来 appendContactNumber() 需要从 15 毫秒(一个电话号码)到大约 20 毫秒(三个电话号码)执行。

// List specific variables
private static ArrayList<String> Contacts;
private static ArrayList<String> Numbers;
private static ArrayList<Bitmap> Photo;

// ContentResolver query specific variables
private static final Uri CONTACTS_URI = ContactsContract.Contacts.CONTENT_URI;
private static final String[] CONTACTS_PROJECTION = {
        ContactsContract.Contacts._ID,
};
private static final String CONTACTS_SELECTION = ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1";
private static final String CONTACTS_SORT_ORDER = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE LOCALIZED ASC";

private static final Uri PHONES_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
private static final String[] PHONE_PROJECTION = {
        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
        ContactsContract.CommonDataKinds.Phone.NUMBER
};
private static final String PHONE_SELECTION = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ";
private static final String[] PHOTO_PROJECTION = { ContactsContract.Contacts.Photo.PHOTO };

private Context context;

public ContactsLoader(Context context) {
    this.context = context;
}

@Override
public void run()
{
    loadContacts();
}

private void loadContacts() {
    Contacts = new ArrayList<>();
    Numbers = new ArrayList<>();
    Photo = new ArrayList<>();

    // Retrieve all contacts with phone numbers
    Cursor contactsCursor = context.getContentResolver().query(
            CONTACTS_URI,
            CONTACTS_PROJECTION,
            CONTACTS_SELECTION,
            null,
            CONTACTS_SORT_ORDER
    );

    if (contactsCursor != null) {
        while (contactsCursor.moveToNext()) {
            appendContactNumber(contactsCursor.getString(contactsCursor.getColumnIndex(ContactsContract.Contacts._ID)));
        }
        contactsCursor.close();
    }
}

private void appendContactNumber(final String contactId) {
    // Retrieve phone numbers for contact specified by id
    Cursor numbersCursor = context.getContentResolver().query(
            PHONES_URI,
            PHONE_PROJECTION,
            PHONE_SELECTION + contactId,
            null,
            null
    );

    // If phone numbers cursor is not empty
    if (numbersCursor != null) {
        Bitmap thumbnail = getContactThumb(contactId);
        while (numbersCursor.moveToNext()) {
            Contacts.add(numbersCursor.getString(numbersCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
            Numbers.add(numbersCursor.getString(numbersCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
            Photo.add(thumbnail);
        }
        numbersCursor.close();
    }
}

private Bitmap getContactThumb(final String contactId) {
    // Get contact thumbnail for given contactId
    Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(contactId));
    Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
    Cursor thumbnailCursor = context.getContentResolver().query(
            photoUri,
            PHOTO_PROJECTION,
            null,
            null,
            null
    );

    if (thumbnailCursor != null) {
        // If contact thumbnail is not empty
        if (thumbnailCursor.moveToFirst()) {
            Bitmap contactPhoto = BitmapFactory.decodeStream(new ByteArrayInputStream(thumbnailCursor.getBlob(0)));
            thumbnailCursor.close();
            return contactPhoto;
        }
    }
    // Default Bitmap
    return BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_contact_picture);
}

【问题讨论】:

  • 一些额外的时间跟踪结果:现在查询 100 个联系人需要 2.5 秒。使用资源中的默认图像:700 毫秒。在单独的线程中运行图像获取:大约 1 秒。

标签: android performance android-contacts android-contentresolver


【解决方案1】:

我做了一些解决方法:获取照片 URI 比查询 Bitmap 更快。这是我的代码:

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.util.Log;

import java.util.ArrayList;

public class PhoneContactsLoader extends ContactsLoader {

    // Class specific variables
    private ArrayList<String> Numbers;

    public PhoneContactsLoader(Context context) {
        super(context);

        // ContentResolver query specific variables
        URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI.toString();
        PROJECTION = new String[] {
                ContactsContract.Contacts._ID,
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.NUMBER,
                ContactsContract.Contacts.PHOTO_URI
        };
        SELECTION = ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1";
        SORT_ORDER = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
    }

    @Override
    protected void fetchContacts() {
        Contacts = new ArrayList<>();
        Numbers = new ArrayList<>();
        Photos = new ArrayList<>();

        Long timer = System.currentTimeMillis();

        // Retrieve all contacts containing phone numbers
        Cursor contactsCursor = context.getContentResolver().query(
                Uri.parse(URI),
                PROJECTION,
                SELECTION,
                null,
                SORT_ORDER
        );

        if (contactsCursor != null) {
            while (contactsCursor.moveToNext()) {
                Contacts.add(contactsCursor.getString(contactsCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
                Numbers.add(contactsCursor.getString(contactsCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
                String photoUri = contactsCursor.getString(contactsCursor.getColumnIndex(ContactsContract.Contacts.PHOTO_URI));
                if (photoUri != null)
                    Photos.add(photoUri);
                else
                    Photos.add("useDefault");
            }
            contactsCursor.close();
        }
        Log.i("PhoneContactsLoader", "Thread execution time: " + (System.currentTimeMillis() - timer) + " ms");
    }

    @Override
    public ArrayList<String> getNumbers() {
        return Numbers;
    }
}

【讨论】:

    猜你喜欢
    • 2012-02-21
    • 2013-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-11
    相关资源
    最近更新 更多