Android获取联系人详细信息的速度较慢

时间:2016-03-02 21:43:36

标签: android performance android-contacts android-contentresolver

我想显示联系人,其中包含电话号码,但所有已分配的号码。我想提高性能。有没有更有效的方法来做到这一点?就像一次获得所有联系人缩略图一样?这个approach以某种方式失败了,因为游标不是空的,但返回空(?)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);
}

1 个答案:

答案 0 :(得分:0)

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

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