Sakhawat Hossain
Sakhawat Hossain

Reputation: 463

How do I increase the fetching speed of an arraylist?

I am using an Arraylist to fetch all the available contacts in my application. This is not efficient because the Arraylist takes a long time to fetch and populate the Listview as there are almost 600+ contacts.

I'm seeking an alternative approach that would have better performance.

Although I searched for other relevant questions but I was't able to find the convenient one.

Here is my java code:

private List<String> getContactList() {
      List<String> stringList=new ArrayList<>();
      ContentResolver cr = context.getContentResolver();
      Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
        null, null, null, null);

      if ((cur != null ? cur.getCount() : 0) > 0) {
        while (cur != null && 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
               );

               while (pCur.moveToNext()) {
                 String phoneNo = pCur.getString(pCur.getColumnIndex(
                 ContactsContract.CommonDataKinds.Phone.NUMBER));                  
                 Log.v("Data : ",""+id+" "+name+" "+phoneNo);
                 stringList.add(id);
                 stringList.add(name);
                 stringList.add(phoneNo);
               }
               pCur.close();
             }
            }
          }
          if(cur!=null){
            cur.close();
          }
          return stringList;
        }   

Upvotes: 0

Views: 430

Answers (3)

marmor
marmor

Reputation: 28179

Your query is inefficient, you're currently doing a query per contact which is very slow, you can get it all with one big query (which is pretty fast):

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.moveToNext()) {
   long contactId = c.getLong(0);
   String name = c.getString(1);
   String phone = c.getString(2);
   Log.i("Phones", "got contact phone: " + contactId + " - " + name + " - " + phone);
}
c.close();

Upvotes: 1

Brian Tang
Brian Tang

Reputation: 1

If you're worried of speed, I would try to use a Set, although with 600+ contacts in the ArrayList that shouldn't be a problem. It becomes a problem when the data set is in the millions and more. I would try to looking at any other inefficiencies in your code.

In terms of a Set, the two most common Java data structures are HashSet and TreeSet. TreeSet if you want to the set to be ordered. HashSet is a little bit faster, but you lose out on the ordering. Both of which has O(1) access time.

Upvotes: 0

Jackey
Jackey

Reputation: 3234

You could consider using the Paging library: https://developer.android.com/topic/libraries/architecture/paging/

It was designed with the idea that a list only displays a certain number of items, so there's really no need to load way way way more than it can potentially show. For example, a ListView might only show 10 contacts, so there's no need to fetch 600 contacts.

Instead, the Paging library will fetch a smaller amount as the user scrolls, thus erasing the loading time of 600 contacts, the memory for 600 contacts, and etc... thus making it more efficient.

Upvotes: 1

Related Questions