0

I'm iterating through Contacts table and each iteration do iteration on Phone table so it takes appx. 4 seconds to do contact list for 243 contacts (without iterating phone numbers it loads instantly). I'm sure there is a way to make it faster.

Already made projections to fetch only needed columns, but haven't improved that much. Maybe I should improve SQLite query or iterate in some other manner:

Contact realmContact = new Contact();

        Uri uri = Contacts.CONTENT_URI;

        String[] projection = {
                Contacts.LOOKUP_KEY,
                Contacts.DISPLAY_NAME_PRIMARY,
                Contacts.LAST_TIME_CONTACTED,
                Contacts.HAS_PHONE_NUMBER
        };

        String selection = "((" + CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + " NOTNULL) AND ("
                + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
                + CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + " != '' ))";

        Cursor phones = getActivity()
                .getContentResolver()
                .query(uri, projection, selection, null, null);

        while (phones.moveToNext()) {
            String id = phones.getString(phones.getColumnIndex(Contacts.LOOKUP_KEY));

            String name = phones.getString(phones.getColumnIndex(Contacts.DISPLAY_NAME_PRIMARY));

            String lastTimeContacted = phones.getString(phones.getColumnIndex(Contacts.LAST_TIME_CONTACTED));
            long data = Long.parseLong(lastTimeContacted);
            String date = new SimpleDateFormat("dd/MM/yyyy | HH:mm").format(new Date(data));

            if (Integer.parseInt(phones.getString(phones.getColumnIndex(Contacts.HAS_PHONE_NUMBER))) > 0) {
                Cursor pCur = getActivity().getContentResolver().query(
                        CommonDataKinds.Phone.CONTENT_URI,
                        new String[]{CommonDataKinds.Phone.NUMBER},
                        CommonDataKinds.Phone.LOOKUP_KEY + " = ?",
                        new String[]{id}, null);

                int iterationCounter = 0;
                String phoneNumber = "";
                while (pCur.moveToNext()) {
                    phoneNumber += iterationCounter == 0 ?
                            pCur.getString(pCur.getColumnIndex(CommonDataKinds.Phone.NUMBER))
                             : "," + pCur.getString(pCur.getColumnIndex(CommonDataKinds.Phone.NUMBER));

                    iterationCounter += 1;
                }
                realmContact.setNumber(phoneNumber);
                Log.i("asd-number", phoneNumber);
                pCur.close();
            }
            realmContact.setId(id);
            realmContact.setName(name);
            realmContact.setLastTimeContacted(
                    getActivity().getResources()
                            .getString(R.string.contacts_list_fragment_last_call)
                            + date);
            realmContact.setIsBeingSaved(true);
            _realm.insertOrUpdate(realmContact);
jean d'arme
  • 4,033
  • 6
  • 35
  • 70

1 Answers1

0

As @pskink mentioned in the comments, you need to query over the Phone table. To get the list of phones by contact, you can maintain a HashMap from contactId to List of phones.

Here's a little snippet that might help (you'd probably want to tweak the collection a bit to store the display-name only once per contact):

HashMap<Long, ArrayList<String>> phones = new HashMap<Long, ArrayList<String>>();
String[] projection = new String[] { Phone.CONTACT_ID, Phone.DISPLAY_NAME, Phone.NUMBER };
Cursor c = cr.query(Phone.CONTENT_URI, projection, null, null, null);
while (c != null && c.moveToNext()) {
    long contactId = c.getLong(0);
    ArrayList<String> list = phones.get(contactId);
    if (list == null) {
        ArrayList<String> list = new ArrayList<String>();
        phones.put(contactId, list);
    }
    list.add(c.getString(1) + " " + c.getString(2));
}
marmor
  • 27,641
  • 11
  • 107
  • 150