Fetching Contact detail Take A lot of time in andr

2019-07-21 00:59发布

问题:

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;
}

回答1:

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.
    }
}


回答2:

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".