【问题标题】:Too much time taken to save a contact保存联系人的时间过长
【发布时间】:2019-01-18 17:26:49
【问题描述】:

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

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

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

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

ArrayList<ContentProviderOperation> cntProOper = new ArrayList<>();
    int contactIndex = cntProOper.size();

    cntProOper.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
            .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
            .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null).build());

    cntProOper.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
            .withValueBackReference(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, contactIndex)
            .withValue(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
            .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
            .build());

    cntProOper.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, contactIndex)
            .withValue(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
            .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, number)
            .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE).build()); //Type like HOME, MOBILE etc
    try {
        contentResolver.applyBatch(ContactsContract.AUTHORITY, cntProOper);
    } catch (RemoteException | OperationApplicationException exp) {}

【问题讨论】:

  • 我已经发布了 getContactID 方法。请检查
  • 他们都返回了正确的值。并且删除 getContactID 方法没有奏效。耗时相同
  • 另外,我尝试过使用另一段代码。但结果是一样的

标签: android performance android-contacts contactscontract


【解决方案1】:

好的,这里要提很多东西...

对于您的第一个代码,永远不要使用Contacts.People.XX API,严肃地说,对于任何地方的任何东西,请确保您不要从 People 导入任何内容或使用它的任何 API,这是一个非常非常古老的 API多年前已弃用,甚至某些设备不支持。

关于您的第二个代码,我尝试在下面的代码中修复许多错误和问题,但专门针对您的性能要求,请注意,如果您没有为每个联系人提供applyBatch '同时创建多个联系人,可以将许多操作放入您的 ops ArrayList 并一次性应用它们 - 更快!

注意事项:

  1. 对于 100 的缓存大小,这应该会给您 100 倍的提升,但是您可以使用该数字,请注意,如果数字太大,您可能会收到一些 Java 警告“事务太大”并且批处理将失败.
  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());
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 2015-04-10
    相关资源
    最近更新 更多