Reputation: 7164
Hi am currently doing a project related to Contact ,Where I am fetching details from the contact*(Email,Number and Contactname)* and it does well.But the problem is it take a long time to fetch the contact details ( 1000+ contact including contact that sync from social network sites).so that I put a Asynchronous Task
for this purpose ,and it does well but the problem is due to a long time to complete the fetching process ,when I press the back button it crash during the Asynchronous task .My problem does not crash why this fetching contact take a lot of time.Is there way to get the contact
faster. My code to get contact detail is as given below
public void readContact() {
contactname = new ArrayList<String>();
contactnumber = new ArrayList<String>();
companyname_one = new ArrayList<String>();
contactemail = new ArrayList<String>();
people = getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI, null, null, null,
PhoneLookup.DISPLAY_NAME);
while (people.moveToNext()) {
int nameFieldColumnIndex = people
.getColumnIndex(PhoneLookup.DISPLAY_NAME);
String contact = people.getString(nameFieldColumnIndex);
if (contact == null) {
contactname.add("No contact Set");
} else {
contactname.add(contact);
}
String szId = people.getString(people
.getColumnIndexOrThrow(ContactsContract.Contacts._ID));
cursor_one = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "='"
+ szId + "'", null, null);
if (cursor_one.moveToNext()) {
String number = cursor_one.getString(cursor_one
.getColumnIndex(Phone.NUMBER));
contactnumber.add(number);
cursor_one.close();
} else {
contactnumber.add("no number");
cursor_one.close();
}
emails_value = getContentResolver().query(
Email.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "='"
+ szId + "'", null, null);
if (emails_value.moveToNext()) {
email_sorting = emails_value.getString(emails_value
.getColumnIndex(Email.DATA));
checkAll();
} else {
contactemail.add("no email");
emails_value.close();
}
}
people.close();
System.out.println("noz " + contactnumber);
System.out.println("name" + contactname);
System.out.println("email" + contactemail);
System.out.println("noz size " + contactnumber.size());
System.out.println("name size " + contactname.size());
System.out.println("contactemail size " + contactemail.size());
}
The checkAll()
method is patter matching of email as below
public boolean checkAll() {
boolean chkAll = true;
Pattern p1 = Pattern.compile(".+@.+\\.[a-z]+");
Matcher m1 = p1.matcher(email_sorting.trim());
if (!m1.matches()) {
contactemail.add("no email");
contactemail_sort.add("no email");
emails_value.close();
chkAll = false;
} else {
contactemail.add(email_sorting);
contactemail_sort.add(email_sorting);
emails_value.close();
chkAll = true;
}
return chkAll;
}
Upvotes: 2
Views: 1468
Reputation: 773
Ok, I think I finally see the best way for this to work. Instead of pulling all of the contact information out before you create your adapter, you should create a custom CursorAdapter that accepts your people
cursor and populates a custom view with your cursor_one
query that is executed on a background thread. This should take advantage of the natural lazyloading of the ListView and make this work like you want.
If your using at least Android 3.0, you can use Loaders instead of using an AsyncTask.
I found an example of a custom cursor adapter here which is what I used to make my example. There are probably better ways to implement this in code, but this at least shows you which methods to override and what to put in them.
public class ContactListCursorAdapter extends SimpleCursorAdapter {
private Context context;
private int layout;
public ContactListCursorAdapter (Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
this.context = context;
this.layout = layout;
}
// Used to populate new list items
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
Cursor c = getCursor();
final LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(layout, parent, false);
int nameCol = c.getColumnIndex(People.NAME);
String name = c.getString(nameCol);
/**
* Next set the name of the entry.
*/
TextView name_text = (TextView) v.findViewById(R.id.name_entry);
if (name_text != null) {
name_text.setText(name);
}
getDeatils(v,c);
return v;
}
// Used to bind a new item from the adapter to an existing view
@Override
public void bindView(View v, Context context, Cursor c) {
int nameCol = c.getColumnIndex(People.NAME);
String name = c.getString(nameCol);
/**
* Next set the name of the entry.
*/
TextView name_text = (TextView) v.findViewById(R.id.name_entry);
if (name_text != null) {
name_text.setText(name);
}
getDetails(v,c);
}
private void populateDetails(View v, Cursor c) {
// Start your AsyncTask or Loader to get the details.
// Be sure to populate the view with the results in the
// appropriate completion callback.
}
}
Upvotes: 3
Reputation: 1930
My suggestion would be to redefine how your structure works. For instance it is really quick to get the basic information about a contact, the display name and other meta data for instance. Show that in a list or whatever and then when they select or view a contact then load the rest of the information.
This will speed it up a lot. However if you must load everything about a contact at once then yes it will be very slow due to how many queries you need to execute.
Another suggestion would be to show them as the completed to the user. That way there is some progress and they can view it. Instead of just putting a dialog up that says "Loading Wait".
Upvotes: 0