Reading complete contact information in Android My goal is to read complete contact information on an Android application. This is very slow and my understanding is that since the contacts are stored locally in a phone database, it shouldn't take long to fetch complete contact details.

public void readContacts() {
    Log.d("TAG", " -&gt; Into readContacts");
    // Get the ContentResolver
    ContentResolver cr = getContentResolver();
    // Get the Cursor of all the contacts
    Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

    // Move the cursor to first. Also check whether the cursor is empty or not.
    if (cursor.moveToFirst()) {
        // Iterate through the cursor
        do {
            // Get the contacts name
            Contact contactToSave = new Contact();
            contactToSave.setIsUploaded(false);
            String id = cursor.getString(cursor.getColumnIndex(
                    ContactsContract.Contacts._ID));
            Log.d(TAG, " ID " + id);


            String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
            contactToSave.setFirstName(name);
            Log.d(TAG, " Complete Name " + name);

            String orgWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
            String[] orgWhereParams = new String[]{id,
                    ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE};
            Cursor orgCur = cr.query(ContactsContract.Data.CONTENT_URI, null, orgWhere, orgWhereParams, null);

            if (orgCur.moveToFirst()) {
                String orgName = orgCur.getString(orgCur.getColumnIndex(ContactsContract.CommonDataKinds.Organization.DATA));
                String title = orgCur.getString(orgCur.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TITLE));
                contactToSave.setCompany(orgName);
            }
            orgCur.close();

            Cursor emailCur = cr.query(
                    ContactsContract.CommonDataKinds.Email.CONTENT_URI,
                    null,
                    ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",
                    new String[]{id}, null);
            while (emailCur.moveToNext()) {
                // This would allow you get several email addresses
                // if the email addresses were stored in an array
                String email = emailCur.getString(
                        emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                contactToSave.setEmail(email);
            }
            emailCur.close();


            if (Integer.parseInt(cursor.getString(cursor.getColumnIndex(
                    ContactsContract.Contacts.HAS_PHONE_NUMBER))) &gt; 0) {
                Cursor pCur = cr.query(
                        ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                        null,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
                        new String[]{id}, null);
                while (pCur.moveToNext()) {
                    String phoneNumber = pCur.getString(pCur.getColumnIndex(
                            ContactsContract.CommonDataKinds.Phone.NUMBER));
                    contactToSave.setPhone(phoneNumber);
                }
                pCur.close();
            }
            mAdapter.add(contactToSave);
        } while (cursor.moveToNext());
        mAdapter.sort(new Comparator&lt;Contact&gt;() {
            @Override
            public int compare(Contact o1, Contact o2) {
                return o1.getFirstName().compareTo(o2.getFirstName());
            }
        });
    }
    // Close the cursor
    cursor.close();
}



I think creating multiple cursors for different data may be a performance overhead. Is there any way those can be combined? 
Is there any other way to fetch the cursor than running multiple queries using multiple cursors? 
If the answer for the above two questions are negative, then is this the best way possible for such a simple requirement?
Use AsyncQueryHandler, a helper class to help make handling asynchronous ContentResolver queries easier.

It basically wraps the ContentResolver object and handles background execution of its operations (CRUD) as well as passing messages (result) from the between threads (background and main/UI).

Just use to call the queryHandler.startQuery method and you will get callback in onQueryComplete method.

Example

class QueryHandler extends AsyncQueryHandler {

        public QueryHandler(ContentResolver cr) {
            super(cr);
        }

        @Override
        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
            switch (token) {

                case CONTACT_QUERY:
//Do your stuff here
                    if (cursor.moveToFirst()) {
                        // Iterate through the cursor
                        do {

                            String id = cursor.getString(cursor.getColumnIndex(
                                    ContactsContract.Contacts._ID));
                            Log.e(TAG, " ID " + id);

                        } while (cursor.moveToNext());
                    }
                    break;
}
}


Use below method to fetch contact and add projection, selection according to your requirment.

public void fetchContact(){
        queryHandler.startQuery(CONTACT_QUERY, null, ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
    }