8

これは、ここStack Overflowを含むさまざまな場所で多少触れられていることを認識していますが、他の人々が使用した可能性のあるソリューションを探しています。それを念頭に置いて...

私は、ユーザーが最初にすべての連絡先をデスクトップアプリケーションOTAと同期できるアプリケーションを開発しています。これは、サーバーから100件の連絡先のセットを取得し、情報をダウンロードして解析し、Android Contact DBに連絡先を挿入し、これらの連絡先の受信を確認してから、次のセットで前の手順を繰り返すWebサービス呼び出しを介して行われます。同期が完了するまで100件の連絡先。このプロセスは、ユーザーが注文または1000〜2000の連絡先を持っている場合にうまく機能しますが、このアプリケーションの一般的なユーザーは、5000〜6000の連絡先を簡単に持つことができます(パワーユーザーは10000以上)。よろしくお願いします。たとえば、約5300の連絡先のサンプルセットは、完了するまでに約13.5分かかる場合があります。悪くはないが、私は

各ステップにかかる時間を記録しましたが、当然のことながら、AndroidコントラクトDBにデータを挿入することがボトルネックになっているようです。Webを精査した後、何千もの連絡先を挿入することに関してほとんど助けが見つかりませんでしたが、私が見つけたものは次の3つのグループに分類されるようです。

1)ContentProviderOperation-5300の連絡先に対して13.5分のベースラインを提供するGoogle推奨の方法。

2)一括挿入-builkInsertはapplyBatchよりも効率的である傾向があることを読みましたが、これを自分で実装しようとすると、同じ5300の連絡先に対して実際には25分かかりました。これは、RawContact情報を挿入し、結果のURIを保存して、ContentProviderOperationのbackValueReferenceを介してより自然に取得されるbulkInsertのContactsContract.Dataを作成する必要があるためだと感じています。さらに、Androidのソースコードを調べましたが、bulkInsertがひどく効率的であるとは感じません。

3)DatabaseUtils.InsertHelperとトランザクションを使用して最適化された一括挿入を作成する-残念ながら、これは、インスタンス変数として基盤となるDBにアクセスする必要があるため、独自のコンテンツプロバイダーを作成した人々を対象としているようです。これは、ネイティブの連絡先DBを使用して実行できます。

5000以上の連絡先を挿入した経験や、時間を短縮するために調べることができるその他の考えられるアイデアはありますか?または、ContentProviderOperationは、取得するのと同じくらい最適化されていると見なす必要がありますか?

4

2 に答える 2

0

残念ながら、1が最良の選択肢だと思います。iPhoneと比較した場合のオーバーヘッドの大部分は、コンテンツプロバイダーの設計に固有のクロスプロセスIPCにあると思います。

3の分析は正しいです。

ルート権限を取得されたデバイスにはコンテンツプロバイダーを回避するためのオプションがありますが、それがあなたが探しているものではないかと思います。

于 2012-11-26T23:39:42.953 に答える
-1

こんにちは私は数分以内に巨大な連絡先を挿入します私のコードは次のとおりです:

public void insertContact(contactList:List<Contact>){

  val queueSize = 300 //400
            val contactQueue = contactList.size/queueSize

            if(contactQueue > 0) {

                var startIndex = 0
                var endIndex = 0

                var tempList: List<Request.ContactBean>? = null

                totalQueue = contactQueue + 1+smsQueue

                for (i in 0..contactQueue) {

                    startIndex = i * queueSize
                    endIndex = startIndex + queueSize

                    endIndex = if (endIndex < contactList.size) endIndex else contactList.size

                    tempList = contactList.subList(startIndex, endIndex);

                    Log.d(Constant.TAG_RESTORE, "In loop totalQueue: " + contactQueue + " i: " + i
                            + " startIndex: " + startIndex + "endIndex: " + endIndex + " Queuesize: " + tempList.size)

                    restoreContact(tempList);
                }
            }else{
                totalQueue = 1+smsQueue;
                restoreContact(contactList);

            }
}





    private fun restoreContact( contactList: List<Request.ContactBean>) {



        Observable.fromCallable { insertContact(contactList); }
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({
                    totalCompleteOperation++

                    if(totalCompleteOperation === totalQueue){

                        Log.d(Constant.TAG_RESTORE, " in subscribe restoreContact " +
                                "totalCompleteOperation: "+ totalCompleteOperation +" totalQueue "+totalQueue)

                        hideDialog();
                        completeRestore(true)
                    }
                }

                )
    }



    public void insertContact(List<Request.ContactBean> contacts) throws RemoteException, OperationApplicationException {

        final int MAX_OPERATIONS_FOR_INSERTION = 100; //100
        int size = contacts.size();

            ArrayList<ContentProviderOperation> ops = new ArrayList<>();
            for (int i = 0; i < size; i++) {

                createOperations(ops, contacts.get(i));
                if (ops.size() >= MAX_OPERATIONS_FOR_INSERTION) {
                    mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
                    ops.clear();
                }
            }
            if (ops.size() > 0)
                mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 

    }


    private void createOperations(ArrayList<ContentProviderOperation> ops,
                                                  Request.ContactBean contact){
        int backReference = ops.size();
        ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
                .withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DISABLED)
                .build()
        );
            ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                   // .withYieldAllowed(true)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, backReference)
                    .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, contact.getName())
                    .build());

            if (contact.getNumbers() != null && contact.getNumbers().size() > 0) {
                // Adding insert operation to operations list
                // to insert Mobile Number in the table ContactsContract.Data
                ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                        //.withYieldAllowed(true)
                        .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, backReference)
                        .withValue(ContactsContract.Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)
                        .withValue(Phone.NUMBER, contact.getNumbers().get(0).getNumber())
                        .withValue(Phone.TYPE, Phone.TYPE_MOBILE)
                        .build());
                if (contact.getNumbers().size() > 1) {
                    // Adding insert operation to operations list
                    // to  insert Home Phone Number in the table ContactsContract.Data
                    ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                            //.withYieldAllowed(true)
                            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, backReference)
                            .withValue(ContactsContract.Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)
                            .withValue(Phone.NUMBER, contact.getNumbers().get(1).getNumber())
                            .withValue(Phone.TYPE, Phone.TYPE_HOME)
                            .build());
                }

            }
            if (contact.getEmails() != null && contact.getEmails().size() > 0) {
                // Adding insert operation to operations list
                // to insert Work Email in the table ContactsContract.Data
                ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                       // .withYieldAllowed(true)
                        .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, backReference)
                        .withValue(ContactsContract.Data.MIMETYPE, Email.CONTENT_ITEM_TYPE)
                        .withValue(Email.ADDRESS, contact.getEmails().get(0).getAddress())
                        .withValue(Email.TYPE, Email.TYPE_WORK)
                        .build());
            }
            if (contact.getEmails().size() > 1) {
                // Adding insert operation to operations list
                // to insert Home Email in the table ContactsContract.Data
                ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                       // .withYieldAllowed(true)
                        .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, backReference)
                        .withValue(ContactsContract.Data.MIMETYPE, Email.CONTENT_ITEM_TYPE)
                        .withValue(Email.ADDRESS, contact.getEmails().get(1).getAddress())
                        .withValue(Email.TYPE, Email.TYPE_HOME)
                        .build());
            }

    }

This code will insert huge contact list in very less time.
于 2018-04-05T12:37:04.350 に答える