22

私のプロジェクトでは、連絡先の取得に時間がかかります。

  • 連絡を取る時間を減らす方法は何ですか
  • 私の電話には1000人の連絡先があると仮定します。
  • 現在、すべての連絡先を読み込むのに2分以上かかります

接点をロードする時間を短縮するにはどうすればよいですか?何かご意見は?

初期メソッドをプログラミングするときに、次のリンクを参照しました。

http://www.coderzheaven.com/2011/06/13/get-all-details-from-contacts-in-android/

4

6 に答える 6

31

ここでより良い解決策.....

private static final String[] PROJECTION = new String[] {
        ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
        ContactsContract.Contacts.DISPLAY_NAME,
        ContactsContract.CommonDataKinds.Phone.NUMBER
    };
.
.
.

ContentResolver cr = getContentResolver();
        Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null);
        if (cursor != null) {
            try {
                final int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
                final int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);

                String name, number;
                while (cursor.moveToNext()) {
                    name = cursor.getString(nameIndex);
                    number = cursor.getString(numberIndex);
                }
            } finally {
                cursor.close();
            }
        }

乾杯...:)

于 2015-02-24T07:13:23.350 に答える
10

合計時間は、連絡先テーブルからアクセスしようとしているフィールドによって異なります。アクセスするフィールドが少ないということは、ループが少なく、処理が少ないため、結果が速くなることを意味します。

また、連絡先のフェッチ操作を高速化するために、毎回ContentResolverでクエリを呼び出す代わりにContentProvideClientを使用できます。これにより、最初に必要なContentProviderをクエリしてからテーブルにクエリを実行するのではなく、特定のテーブルをクエリするようになります。

ContentProviderClientのインスタンスを作成します

ContentResolver cResolver=context.getContextResolver();
ContentProviderClient mCProviderClient = cResolver.acquireContentProviderClient(ContactsContract.Contacts.CONTENT_URI);

次に、このmCProviderClientを再利用して、通話の連絡先(任意のContentProviderからのデータ)データを取得します。たとえば、次の方法では、1つのフィールドにのみアクセスしています。

private ArrayList<String> fetchContactsCProviderClient()
    {
        ArrayList<String> mContactList = null;
        try
        {
            Cursor mCursor = mCProviderClient.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
            if (mCursor != null && mCursor.getCount() > 0)
            {
                mContactList = new ArrayList<String>();
                mCursor.moveToFirst();
                while (!mCursor.isLast())
                {
                    String displayName = mCursor.getString(mCursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
                    mContactList.add(displayName);
                    mCursor.moveToNext();
                }
                if (mCursor.isLast())
                {
                    String displayName = mCursor.getString(mCursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
                    mContactList.add(displayName);
                }
            }

            mCursor.close();
        }
        catch (RemoteException e)
        {
            e.printStackTrace();
            mContactList = null;
        }
        catch (Exception e)
        {
            e.printStackTrace();
            mContactList = null;
        }

        return mContactList;
    }
于 2012-07-13T07:56:59.937 に答える
8

他のアプリと同じように、Contactをより速くロードします。

私はこのコードを複数の連絡先でテストしましたが、他のアプリと同じように正常に動作し、連絡先500 msを読み込むことができます(0.5秒以内)1000+

合計時間は、連絡先テーブルからアクセスしようとしているフィールドによって異なります。

要件に応じてクエリを管理し、不要なフィールドにアクセスしないでください。アクセスするフィールドが少ないということは、ループが少なく、処理が少ないため、結果が速くなることを意味します。

接触している正しいテーブルにアクセスすることは、接触のロード時間を短縮するのにも役立ちます。

連絡先をより高速にロードするためのクエリ最適化projection

 String[] projection = {
            ContactsContract.Data.MIMETYPE,
            ContactsContract.Data.CONTACT_ID,
            ContactsContract.Contacts.DISPLAY_NAME,
            ContactsContract.Contacts.PHOTO_URI,
            ContactsContract.Contacts.STARRED,
            ContactsContract.RawContacts.ACCOUNT_TYPE,
            ContactsContract.CommonDataKinds.Contactables.DATA,
            ContactsContract.CommonDataKinds.Contactables.TYPE
    };

選択と選択引数

String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)" + " AND " /*+ ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" + 1 + "' AND "*/ +
            ContactsContract.Data.HAS_PHONE_NUMBER + " = '" + 1 + "'";

    String[] selectionArgs = {
            ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
            ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
    };

連絡先をアルファベット順に注文するには、次のコードを使用します

 try {
        Collections.sort(listview_address, new Comparator<ContactBook>() {
            @Override
            public int compare(ContactBook lhs, ContactBook rhs) {
                return lhs.name.toUpperCase().compareTo(rhs.name.toUpperCase());
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }

以下は完全なソースコードです

 public void initeContacts() {
    List<ContactBook> listview_address = new LinkedList<ContactBook>();
    SparseArray<ContactBook> addressbook_array = null;
    {
        addressbook_array = new SparseArray<ContactBook>();

        long start = System.currentTimeMillis();

        String[] projection = {
                ContactsContract.Data.MIMETYPE,
                ContactsContract.Data.CONTACT_ID,
                ContactsContract.Contacts.DISPLAY_NAME,
                ContactsContract.Contacts.PHOTO_URI,
                ContactsContract.Contacts.STARRED,
                ContactsContract.RawContacts.ACCOUNT_TYPE,
                ContactsContract.CommonDataKinds.Contactables.DATA,
                ContactsContract.CommonDataKinds.Contactables.TYPE
        };

        String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)" + " AND " /*+ ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" + 1 + "' AND "*/ +
                ContactsContract.Data.HAS_PHONE_NUMBER + " = '" + 1 + "'";

        String[] selectionArgs = {
                ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
                ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
        };

        String sortOrder = ContactsContract.Contacts.SORT_KEY_ALTERNATIVE;

        Uri uri = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
            uri = ContactsContract.CommonDataKinds.Contactables.CONTENT_URI;
        } else {
            uri = ContactsContract.Data.CONTENT_URI;

        }
        // we could also use Uri uri = ContactsContract.Data.CONTENT_URI;
        // we could also use Uri uri = ContactsContract.Contact.CONTENT_URI;

        Cursor cursor = getActivity().getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);


        final int mimeTypeIdx = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE);
        final int idIdx = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
        final int nameIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
        final int dataIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.DATA);
        final int photo = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.PHOTO_URI);
        final int typeIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.TYPE);
        final int account_type = cursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_TYPE);
        while (cursor.moveToNext()) {
            int contact_id = cursor.getInt(idIdx);
            String photo_uri = cursor.getString(photo);
            String contact_name = cursor.getString(nameIdx);
            String contact_acc_type = cursor.getString(account_type);
            int contact_type = cursor.getInt(typeIdx);
            String contact_data = cursor.getString(dataIdx);
            ContactBook contactBook = addressbook_array.get(contact_id);

           /* if (contactBook == null) {
                //list  contact add to avoid duplication
                //load All contacts fro device
                //to add contacts number with name add one extra veriable in ContactBook as number and pass contact_data this give number to you (contact_data is PHONE NUMBER)
                contactBook = new ContactBook(contact_id, contact_name, getResources(), photo_uri, contact_acc_type, "phone number");
                addressbook_array.put(contact_id, contactBook);
                listview_address.add(contactBook);

            }*/

            String Contact_mimeType = cursor.getString(mimeTypeIdx);
            //here am checking Contact_mimeType to get mobile number asociated with perticular contact and email adderess asociated
            if (Contact_mimeType.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {

                if (contactBook != null) {
                    contactBook.addEmail(contact_type, contact_data);
                }

            } else {
                if (contactBook == null) {
                    //list  contact add to avoid duplication
                    //load All contacts fro device
                    //to add contacts number with name add one extra veriable in ContactBook as number and pass contact_data this give number to you (contact_data is PHONE NUMBER)
                    contactBook = new ContactBook(contact_id, contact_name, getResources(), photo_uri, contact_acc_type, "phone number");
                    addressbook_array.put(contact_id, contactBook);
                    listview_address.add(contactBook);

                }
               // contactBook.addPhone(contact_type, contact_data);


            }


        }

        cursor.close();


        try {
            Collections.sort(listview_address, new Comparator<ContactBook>() {
                @Override
                public int compare(ContactBook lhs, ContactBook rhs) {
                    return lhs.name.toUpperCase().compareTo(rhs.name.toUpperCase());
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

私がコメントした上記のコードで次のコードを使用できます。単一の連絡先を複数の番号でクラブします。単一の連絡先に関連付けられたすべての番号を取得するには、Objectクラスの配列を使用します。

 if (contactBook == null) {
            //irst  contact add to avoid duplication
            //load All contacts fro device
            contactBook = new ContactBook(contact_id, contact_name, getResources(), photo_uri, contact_acc_type, "");
            addressbook_array.put(contact_id, contactBook);
            listview_address.add(contactBook);
        }

        String Contact_mimeType = cursor.getString(mimeTypeIdx);
        //here am checking Contact_mimeType to get mobile number asociated with perticular contact and email adderess asociated
        if (Contact_mimeType.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {

            contactBook.addEmail(contact_type, contact_data);

        } else {

            contactBook.addPhone(contact_type, contact_data);

        }

オブジェクトクラス

public class ContactBook {
public int id;
public Resources res;
public String name;
public String photo;
public String contact_acc_type;
public SparseArray<String> emails;
public SparseArray<String> phones;
/*  public LongSparseArray<String> emails;
public LongSparseArray<String> phones;*/
public String header = "";


public ContactBook(int id, String name, Resources res, String photo, String contact_acc_type, String header) {
    this.id = id;
    this.name = name;
    this.res = res;
    this.photo = photo;
    this.contact_acc_type = contact_acc_type;
    this.header = header;
}

@Override
public String toString() {
    return toString(false);
}

public String toString(boolean rich) {

    //testing method to check ddata
    SpannableStringBuilder builder = new SpannableStringBuilder();
    if (rich) {
        builder.append("id: ").append(Long.toString(id))
                .append(", name: ").append("\u001b[1m").append(name).append("\u001b[0m");
    } else {
        builder.append(name);
    }

    if (phones != null) {
        builder.append("\n\tphones: ");
        for (int i = 0; i < phones.size(); i++) {
            int type = (int) phones.keyAt(i);
            builder.append(ContactsContract.CommonDataKinds.Phone.getTypeLabel(res, type, ""))
                    .append(": ")
                    .append(phones.valueAt(i));
            if (i + 1 < phones.size()) {
                builder.append(", ");
            }
        }
    }

    if (emails != null) {
        builder.append("\n\temails: ");
        for (int i = 0; i < emails.size(); i++) {
            int type = (int) emails.keyAt(i);
            builder.append(ContactsContract.CommonDataKinds.Email.getTypeLabel(res, type, ""))
                    .append(": ")
                    .append(emails.valueAt(i));
            if (i + 1 < emails.size()) {
                builder.append(", ");
            }
        }
    }
    return builder.toString();
}

public void addEmail(int type, String address) {
    //this is the array in object class where i am storing contact all emails of perticular contact (single)
    if (emails == null) {
        //   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        emails = new SparseArray<String>();
        emails.put(type, address);
        /*} else {
            //add emails to array below Jelly bean //use single array list
        }*/
    }
}

public void addPhone(int type, String number) {
    //this is the array in object class where i am storing contact numbers of perticular contact
    if (phones == null) {
        //  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        phones = new SparseArray<String>();
        phones.put(type, number);
       /* } else {
            //add emails to array below Jelly bean //use single array list
        }*/
    }
}}
于 2017-09-29T13:12:31.823 に答える
5

最小時間で連絡先をロードするための最適な解決策は、カーソルに連絡先を照会するときに、投影と選択の引数の概念を使用することです。

これは次の方法で行うことができます

void getAllContacts() {
    long startnow;
    long endnow;

    startnow = android.os.SystemClock.uptimeMillis();
    ArrayList arrContacts = new ArrayList();

    Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
    String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER;
    Cursor cursor = ctx.getContentResolver().query(uri, new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER,   ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.Contacts._ID}, selection, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");

    cursor.moveToFirst();
    while (cursor.isAfterLast() == false) {

        String contactNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
        String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
        int phoneContactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
        int contactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID));
        Log.d("con ", "name " + contactName + " " + " PhoeContactID " + phoneContactID + "  ContactID " + contactID)

        cursor.moveToNext();
    }
    cursor.close();
    cursor = null;

    endnow = android.os.SystemClock.uptimeMillis();
    Log.d("END", "TimeForContacts " + (endnow - startnow) + " ms");
}

上記の方法では、接点のロードに400ms(1秒未満)かかりましたが、通常の方法では10〜12秒かかりました。

詳細については、この投稿を参考にしてください。http: //www.blazin.in/2016/02/loading-contacts-fast-from-android.html

于 2016-02-19T10:55:42.523 に答える
4

データとともに時間が増える場合は、新しいクエリを実行して、すべての連絡先の電話/電子メールを取得している可能性があります。を使用して電話/電子メールフィールドをクエリすると、ContactsContract.CommonDataKinds.Phone.NUMBER連絡先ごとに1つの電話を取得するだけです。解決策は、フィールドを投影し、連絡先IDでそれらを結合することです。

Kotlinでの私の解決策は次のとおりです(ID、名前、すべての電話と電子メールを抽出します):

val projection = arrayOf(
        ContactsContract.Data.MIMETYPE,
        ContactsContract.Data.CONTACT_ID,
        ContactsContract.Contacts.DISPLAY_NAME,
        ContactsContract.CommonDataKinds.Contactables.DATA

)
val selection = "${ContactsContract.Data.MIMETYPE} in (?, ?)"

val selectionArgs = arrayOf(
        ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
        ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)

val contacts = applicationContext
        .contentResolver
        .query(ContactsContract.Data.CONTENT_URI, projection, selection, selectionArgs, null)
        .run {
            if (this == null) {
                throw IllegalStateException("Cursor null")
            }
            val contactsById = mutableMapOf<String, LocalContact>()
            val mimeTypeField = getColumnIndex(ContactsContract.Data.MIMETYPE)
            val idField = getColumnIndex(ContactsContract.Data.CONTACT_ID)
            val nameField = getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)
            val dataField = getColumnIndex(ContactsContract.CommonDataKinds.Contactables.DATA)

            while (moveToNext()) {
                val mimeType = getString(mimeTypeField)
                val id = getString(idField)
                var contact = contactsById[id]
                if (contact == null) {
                    val name = getString(nameField)
                    contact = LocalContact(id = id, fullName = name, phoneNumbers = listOf(), emailAddresses = listOf())
                }
                val data = getString(dataField)
                when(getString(mimeTypeField)) {
                    ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE ->
                        contact = contact.copy(emailAddresses = contact.emailAddresses + data)
                    ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE ->
                        contact = contact.copy(phoneNumbers = contact.phoneNumbers + data)
                }
                contactsById[id] = contact
            }
            close()
            contactsById.values.toList()
        }

そして参考までに、私のLocalContactモデル:

data class LocalContact(
        val id: String,
        val fullName: String?,
        val phoneNumbers: List<String>,
        val emailAddresses: List<String>
)
于 2020-03-19T13:28:13.147 に答える
0

これがより良い解決策だと思います:

public ContentValues getAllContacts() {
    ContentValues contacts = new ContentValues();
    ContentResolver cr = getContentResolver();
    Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

    if (cur != null && cur.getCount() > 0) {
        while (cur.moveToNext()) {
            String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
            String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

            if (cur.getInt(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {
                Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{id}, null);
                if (pCur != null) {
                    while (pCur.moveToNext()) {
                        String phoneNo = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                        contacts.put(phoneNo, name);
                    }
                    pCur.close();
                }
            }
        }
        cur.close();
    }
    return contacts;
}

使用するには、この行を1回呼び出す必要があります。

ContentValues contacts = new ContentValues();
contacts = getAllContacts();

連絡先の名前を番号で取得する場合は、次を使用します。

String number = "12345";
String name = (String) G.contacts.get(number);

このアルゴリズムは少し高速です...

于 2017-07-29T04:45:09.830 に答える