【问题标题】:Batch / bulk delete contacts - Taking way to long批量/批量删除联系人 - 需要很长时间
【发布时间】:2014-02-13 12:34:04
【问题描述】:

我正在开发一个 REST 应用程序来批量删除联系人(我的意思是联系人,而不是原始联系人)。删除一批约 116 个联系人需要 3 多分钟,在我看来,这已经太多了。有时它会打印出Contacts deleted,但它们仍在手机的联系人列表中,有时它们会被真正删除。

谁能指出问题出在哪里?

我收到了一个JSONArray,其中包含应删除的联系人 ID(以及一些其他详细信息,但仅在此方法中使用了 ID)。

这是我的删除联系代码:

public Boolean deleteBatchContact(final JSONArray jsonArray) throws JSONException, RemoteException, OperationApplicationException
{
    final ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
    final Long startTime = System.currentTimeMillis();

    if(jsonArray.length() != 0) // there must be something in the JSONArray
    {
        for(int i = 0; i < jsonArray.length(); i++)
        {
            final JSONObject jsonContactObject = jsonArray.getJSONObject(i);
            final String contactId = jsonContactObject.getString("id");
            Long id = Long.parseLong(contactId);

            ops.add(ContentProviderOperation.newDelete(ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(contactId)))
                    .withYieldAllowed(true)
                    .build());
        }

        try {
            final ContentProviderResult[] cpr = contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
            final Long endTimeTry = System.currentTimeMillis();
            final Integer numberOfContactsDeleted = cpr.length;

            if(numberOfContactsDeleted > 0)
            {
                Log.d(TAG, numberOfContactsDeleted + " Contacts deleted!");
                final Long totalSuccess = endTimeTry-startTime;
                Log.d(TAG, "Total Time (Sucess): " + totalSuccess);

                return true;
            }
            else 
            {
                Log.d(TAG, "Menor ou igual a zero...");
                final Long totalFailed = endTimeTry-startTime;
                Log.d(TAG, "Total Time (No deletes): " + totalFailed);
                return false;
            }

        } catch (Exception e) {
            Log.d(TAG, "deleteBatchContact: " + e.getMessage());
            return false;
        }
    }
    Long endTimeReturnFalse = System.currentTimeMillis();
    Long totalTimeReturnFalse = endTimeReturnFalse - startTime;
    Log.d(TAG, "Total time return false: " + totalTimeReturnFalse);
    return false;
}

这里是我调用deleteBatchContact 方法的地方:

else if(type.equalsIgnoreCase("delete"))
    {
        Log.d(TAG, "DELETE REQUEST");
        String strJson = request.getEntityAsText();
        int age = response.getAge();
        Log.d(TAG, "age1: " + age);
        Log.d(TAG, "is commited1? " + response.isCommitted());
        try {
            Log.d(TAG, "Try...");
            JSONArray jsonArray = new JSONArray(strJson);
            if(processDelete(jsonArray) == true)
            {
                Log.d(TAG, "Response -> Deleted with Success!");
                response.setEntity("Deleted with success!", MediaType.TEXT_ALL);
                age = response.getAge();
                Log.d(TAG, "age2: " + age);
                Log.d(TAG, "is commited2? " + response.isCommitted());
            }
            else
            {
                Log.d(TAG, "Response -> No contacts deleted...");
                response.setEntity("No contacts deleted...", MediaType.TEXT_ALL);
                age = response.getAge();
                Log.d(TAG, "age3: " + age);
                Log.d(TAG, "is commited3? " + response.isCommitted());
            }
        } catch (RemoteException e) {
            Log.d(TAG, "processDelete exception: " + e.getMessage());
            e.printStackTrace();
        } catch (JSONException e) {
            Log.d(TAG, "processDelete exception: " + e.getMessage());
            e.printStackTrace();
        } catch (OperationApplicationException e) {
            Log.d(TAG, "processDelete exception: " + e.getMessage());
            e.printStackTrace();
        }

    }

这是输出:

02-13 01:28:04.484: D/ContactRestlet(17638): DELETE REQUEST
02-13 01:28:04.507: D/ContactRestlet(17638): age1: 0
02-13 01:28:04.507: D/ContactRestlet(17638): is commited1? false
02-13 01:28:04.507: D/ContactRestlet(17638): Try...
02-13 01:30:04.671: D/ContactRestlet(17638): DELETE REQUEST
02-13 01:30:04.671: D/ContactRestlet(17638): age1: 0
02-13 01:30:04.671: D/ContactRestlet(17638): is commited1? false
02-13 01:30:04.671: D/ContactRestlet(17638): Try...
02-13 01:31:07.468: D/ContactList(17638): 116 Contacts deleted!
02-13 01:31:07.468: D/ContactList(17638): Total Time (Sucess): 182911
02-13 01:31:07.468: D/ContactRestlet(17638): Response -> Deleted with Success!
02-13 01:31:07.472: D/ContactRestlet(17638): age2: 0
02-13 01:31:07.472: D/ContactRestlet(17638): is commited2? false
02-13 01:31:07.476: W/System.err(17638): 2014-02-13 01:31:07    -   -   -   8080    DELETE  /contacts   -   1001    21  12590   62837   http://10.17.1.72:8080  Apache-HttpClient/4.3.1 (java 1.5)  -

编辑: 正如@RocketRandom 所建议的,这是我的新代码:

    public Boolean deleteBatchContact(final JSONArray jsonArray) throws JSONException, RemoteException, OperationApplicationException
{
    final ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
    final Long startTime = System.currentTimeMillis();

    if(jsonArray.length() != 0) // there must be something in the JSONArray
    {
        StringBuilder query = new StringBuilder(" in {");
        for(int i = 0; i < jsonArray.length(); i++)
        {   
            final JSONObject jsonContactObject = jsonArray.getJSONObject(i);
            final String contactId = jsonContactObject.getString("id");

            query.append(contactId).append(",");
        }
        query.deleteCharAt(query.length()-1);
        query.append("}");

        ops.add(ContentProviderOperation.newDelete(Contacts.CONTENT_URI)
        .withSelection(Contacts._ID + " in { 1 , 2 , 3 , 4 , 5, 6, 7, 8, 9}", null).build()); 

        try {
            final ContentProviderResult[] cpr = contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
            final Long endTimeTry = System.currentTimeMillis();
            final Integer numberOfContactsDeleted = cpr.length;

            if(numberOfContactsDeleted > 0)
            {
                Log.d(TAG, numberOfContactsDeleted + " Contacts deleted!");
                final Long totalSuccess = endTimeTry-startTime;
                Log.d(TAG, "Total Time (Sucess): " + totalSuccess);

                return true;
            }
            else 
            {
                Log.d(TAG, "Menor ou igual a zero...");
                final Long totalFailed = endTimeTry-startTime;
                Log.d(TAG, "Total Time (No deletes): " + totalFailed);
                return false;
            }
        } catch (Exception e) {
            Log.d(TAG, "deleteBatchContact: " + e.getMessage());
            return false;
        }
    }
    Long endTimeReturnFalse = System.currentTimeMillis();
    Long totalTimeReturnFalse = endTimeReturnFalse - startTime;
    Log.d(TAG, "Total time return false: " + totalTimeReturnFalse);
    return false;
}

这是输出:

03-06 01:42:10.367: D/ContactList(8925): 1 Contacts deleted!
03-06 01:42:10.367: D/ContactList(8925): Total Time (Sucess): 84

现在它没有删除任何联系人,你能发现错误在哪里吗? 即使它说删除了一个联系人,也没有删除。所有这些联系人 ID 都是有效的(它们确实存在于我的联系人表中,我已经从我的设备上下载并检查了它。)

【问题讨论】:

    标签: android contacts android-contacts contactscontract


    【解决方案1】:

    编辑:删除了之前建议的解决方案。这是行不通的。 (对不起)

    我检查了联系人提供程序代码,仅原始联系人支持批量删除。对于联系人,他们在那里所做的只是返回,他们在那里有一个不错的小“TODO”。

    您的原始代码是正确的方法。 当您删除联系人(没有 isCallerSyncAdapter 标志)时,提供者会做什么,它会查询具有该联系人 ID 的所有原始联系人,并一一设置脏标志(这需要一段时间)

    我最后尝试了:

    03-19 13:28:11.620: D/tmp(5912): 188 联系人已删除!

    03-19 13:28:11.620:D/tmp(5912):总时间(成功):387496

    即每次接触大约需要 2 秒,这太可怕了。 但是我看不到在不修改 Android Contacts ContentProvider 的情况下让它更快的方法

    【讨论】:

    • 据我所知,Android 不允许您直接对 SQL Lite 数据库执行此类查询。
    • 我的意思是使用 android 提供的 API 创建一个类似的查询。可以调整 where 字符串以合并上述查询。用示例更新了帖子。
    • 请检查我编辑的问题。现在它不会删除任何联系人。
    • 我看到的一个错误是应该使用 () 而不是 {}。这是我的示例代码中的一个错误。现在编辑和更正它。
    • 很抱歉最初的建议不正确。我已经更新了我原来的帖子。
    猜你喜欢
    • 1970-01-01
    • 2017-03-08
    • 1970-01-01
    • 2013-05-02
    • 2018-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多