Reputation: 21
I have to create a listview with the name and the phone number of all contact on the phone. My code is working but is taking too much time when the user have a lot of contacts. Do you have idea of how I can improve it?
public List<Contact> fetchContacts () {
String phoneNumber = null;
String email = null;
Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
String _ID = ContactsContract.Contacts._ID;
String DISPLAY_NAME = ContactsContract.Contacts.DISPLAY_NAME;
String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;
Uri PhoneCONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String Phone_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
String NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;
ContentResolver contentResolver = getContentResolver();
Cursor cursor = getContentResolver().query(CONTENT_URI, null, null, null, DISPLAY_NAME + " ASC");
List<Contact> contactList = new ArrayList<Contact>();
// Loop for every contact in the phone
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
String contact_id = cursor.getString(cursor.getColumnIndex( _ID ));
String name = cursor.getString(cursor.getColumnIndex( DISPLAY_NAME ));
int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex( HAS_PHONE_NUMBER )));
if (hasPhoneNumber > 0) {
Cursor phoneCursor = contentResolver.query(PhoneCONTENT_URI, null, Phone_CONTACT_ID + " = ?", new String[]{contact_id}, null);
phoneCursor.moveToNext();
phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(NUMBER));
phoneCursor.close();
Contact contacto = new Contact();
contacto.name = name;
contacto.phone = phoneNumber;
contacto.id = contact_id;
contactList.add(contacto);
}
}
}
return contactList;
}
Upvotes: 0
Views: 49
Reputation: 1855
you are fetching ALL the contacts on the phone at once. this is the reason it takes time. what you should do instead is use a CursorAdapter: http://developer.android.com/reference/android/widget/CursorAdapter.html
you define the FROM (selection), TO (projection), and the list item view layout:
public SimpleCursorAdapter(android.content.Context context, int layout, android.database.Cursor c, java.lang.String[] from, int[] to, int flags) { /* compiled code */ }
than you set the adapter on the ListView with:
mListView.setAdapter(mAdapter);
What the adapter does is actually fetch contacts in chunks, only for the visible views (with some extra), but not all the contacts at once.
Another tip: you need to implement:
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
...
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
...
}
bindView should only bind the data coming from the cursor, newView creates the new view and set pointers to the inner views for faster access in bindView (basically you should do all the .findViewById(...) in newView.
Tip 2: look for ViewHolder pattern for faster views recycling in the listView
Upvotes: 1