保存联系人花费了太多时间

时间:2019-01-18 17:26:49

标签: android performance android-contacts contactscontract

我在电话簿中保存了大约250个联系人。每个联系人大约需要1秒钟才能保存到联系人列表中。在我的应用程序中,我可能必须保存10,000多个联系人。然后将需要几个小时才能保存它们。因此,我想要一种快速保存所有联系人的方法。您的回答将对我有很大帮助:)

这是我用于for循环以保存联系人的方法-

//calculating the size ratio might be more difficult than this, assume this is pseudocode
var sizeRatio = xrDetectedImageTarget.width / xrDetectionImage.targetWidthInMeters;

var placedModel = Instantiate(prefabModel, newPosition, newRotation, parentTransform);
placedModel.transform.localScale = this.transform.localScale * sizeRatio;

编辑-也尝试过此代码,但结果相同

public static String saveNewContact(String name, String number, ContentResolver contentResolver){
    ContentValues values = new ContentValues();
    values.put(Contacts.People.NUMBER, number);
    values.put(Contacts.People.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM);
    values.put(Contacts.People.LABEL, name);
    values.put(Contacts.People.NAME, name);
    Uri dataUri = contentResolver.insert(Contacts.People.CONTENT_URI, values);
    Uri updateUri = Uri.withAppendedPath(dataUri, Contacts.People.Phones.CONTENT_DIRECTORY);
    values.clear();
    values.put(Contacts.People.Phones.TYPE, Contacts.People.TYPE_MOBILE);
    values.put(Contacts.People.NUMBER, number);
    updateUri = contentResolver.insert(updateUri, values);
    return getContactID(updateUri, contentResolver);
}


public static String getContactID(Uri contactUri, ContentResolver contentResolver){
    String id = "";
    Cursor cursor = contentResolver.query(contactUri, null,
            null, null, null);
    if (cursor != null && cursor.moveToFirst()) {
        int idx = cursor.getColumnIndex(ContactsContract.Contacts._ID);
        id = cursor.getString(idx);
    }

    return id;
}

1 个答案:

答案 0 :(得分:0)

好,在这里有很多事情要提...

对于第一个代码,永远不要使用Contacts.People.XX API,要认真对待任何地方的任何事物,请确保不要从People导入任何东西或使用其API中的任何一个,这是非常古老的许多年前已不推荐使用该API,某些设备甚至不支持该API。

关于您的第二个代码,我尝试在下面的代码中修复的许多错误和问题,但特别是出于您对性能的要求,请注意,您不必为每个联系人都applyBatch如果您要一次创建多个联系人,则可以在ops ArrayList内进行许多操作,然后一次全部应用它们-更快!

注意:

  1. 这应该为您提供100倍的高速缓存,以增加100的缓存大小,但是您可以使用该数字,只是请注意,如果该数字太大,则可能会冒一些Java警告“ Transaction Too Large”,并且该批处理将失败。
  2. 始终为ACCOUNT_TYPE / ACCOUNT_NAME值提供与您的应用相关的内容,我在此代码中添加了两个您需要的const值MY_ACCOUNT_TYPE / MY_ACCOUNT_NAME定义。


ArrayList<ContentProviderOperation> ops = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
    createContact(ops, name, phone);
    if (i % 100 == 0) { // experiment with different batch sizes to achieve best performance times
        try {
            contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
        } catch (RemoteException | OperationApplicationException e) {
            Log.e(TAG, "error applying batch: ", e);
        }
        ops = new ArrayList<>();
    }
}

private void createContact(ArrayList<ContentProviderOperation> ops, String name, String phone) {

    ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
            .withValue(RawContacts.ACCOUNT_TYPE, MY_ACCOUNT_TYPE)
            .withValue(RawContacts.ACCOUNT_NAME, MY_ACCOUNT_NAME).build());

    int indexOfRawContactIdOperation = ops.size() - 1;

    ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, indexOfRawContactIdOperation)
            .withValue(ContactsContract.Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
            .withValue(StructuredName.DISPLAY_NAME, name)
            .build());

    ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, indexOfRawContactIdOperation)
            .withValue(ContactsContract.Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)
            .withValue(Phone.NUMBER, number)
            .withValue(Phone.TYPE, Phone.TYPE_MOBILE).build());
}