How to display contacts in Android using AsyncTask

2020-03-08 07:17发布

问题:

I'm trying to list all the contacts in mobile. So far everything was working fine, but when I thought of running my code in AsyncTask I'm getting nothing on screen.

Here is code snippet

protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_call_list);

    lvCallList = (ListView) findViewById(R.id.lv_call_list);

    new AsyncTask<Void, Void, Void>() 
    {
        @Override
        protected void onPreExecute() 
        {
            pd = ProgressDialog.show(CallListActivity.this,
                    "Loading..", "Please Wait", true, false);
        }// End of onPreExecute method

        @Override
        protected Void doInBackground(Void... params) 
        {
            getContacts();

            return null;
        }// End of doInBackground method

        @Override
        protected void onPostExecute(Void result)
        {
            pd.dismiss();

            lvCallList.setAdapter(new CustomAdapter(CallListActivity.this));

        }//End of onPostExecute method
    }.execute((Void[]) null);
     count = this.displayContactName.size();
    thumbnailsselection = new boolean[count];
}


private void getContacts()
{
    ContentResolver cr = getContentResolver();
    Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null,null, null, null);
    if (cur.getCount() > 0)
    {
        while (cur.moveToNext())
        {
            String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
            String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

            this.displayContactName.add(name);
            if (Integer.parseInt(cur.getString(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 phoneNumber = pCur.getString(pCur.getColumnIndex( ContactsContract.CommonDataKinds.Phone.NUMBER));
                    this.displayContactNumber.add(phoneNumber);
                } 
                pCur.close();
            }
        }
    }
}

 public class CustomAdapter extends BaseAdapter 
{
    /*
     * Variables Declaration section
     */
    private Context mContext;

    public CustomAdapter(Context context) 
    {
        mContext = context;
    }//End of CustomAdapter constructor

    public int getCount() 
    {
        return count;
    }//End of getCount method

    public Object getItem(int position) 
    {
        return position;
    }//End of getItem method

    public long getItemId(int position) 
    {
        return position;
    }//End of getItemId method

    public View getView(int position, View convertView, ViewGroup parent) 
    {

        return convertView;
    }//End of getView method
}//End of CustomAdapter instance inner class

class ViewHolder 
{
    TextView textviewName;
    TextView textviewNumber;
    CheckBox checkbox;
    int id;
}//End of ViewHolder instance inner class

displayContactName value using break point at pd.dismiss(); is

displayContactName  ArrayList  (id=830007844896)    
array   Object[12]  (id=830007907208)   
    [0] "Rrs" (id=830007907144) 
    [1] "Fgsd" (id=830007920424)    
    [2] null    
    [3] null    
    [4] null    
    [5] null    
    [6] null    
    [7] null    
    [8] null    
    [9] null    
    [10]    null    
    [11]    null    
modCount    2   
size    2   

I don't know what's wrong in my code, when I don't use AsyncTask then my code works perfectly fine, but when I use AsyncTask problem comes. Please help me to solve this puzzle.

Thanks in advance.

回答1:

You cannot update ui in doInbackground. You should update ui on the ui thread. Set the adapter in onPostExecute.

You can also use runOnUiThread.

Example

To display contact names.

public class MainActivity extends Activity {

    ListView lvCallList;
    ProgressDialog pd;
    ArrayList<String> aa = new ArrayList<String>();
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        lvCallList = (ListView) findViewById(R.id.list);

        new AsyncTask<Void, Void, Void>() 
        {
            @Override
            protected void onPreExecute() 
            {
                pd = ProgressDialog.show(MainActivity.this,
                        "Loading..", "Please Wait", true, false);
            }// End of onPreExecute method

            @Override
            protected Void doInBackground(Void... params) 
            {
                getContacts();

                return null;
            }// End of doInBackground method

            @Override
            protected void onPostExecute(Void result)
            {
                pd.dismiss();
             ArrayAdapter<String>   arrayAdapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,aa);
             lvCallList.setAdapter(arrayAdapter);

            }//End of onPostExecute method
        }.execute((Void[]) null);
    }
        private void getContacts()
        {
            ContentResolver cr = getContentResolver();
            Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null,null, null, null);
            if (cur.getCount() > 0)
            {
                while (cur.moveToNext())
                {
                    String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
                    String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

                    aa.add(name);
                    if (Integer.parseInt(cur.getString(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 phoneNumber = pCur.getString(pCur.getColumnIndex( ContactsContract.CommonDataKinds.Phone.NUMBER));
                          //  this.displayContactNumber.add(phoneNumber);
                        } 
                        pCur.close();
                    }
                }
            }
        }
    }

Snap shot on my mobile

Edit: 2

public class MainActivity extends Activity {

    ListView lvCallList;
    ProgressDialog pd;
    ArrayList<String> aa = new ArrayList<String>();
    ArrayList<String> num= new ArrayList<String>();
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        lvCallList = (ListView) findViewById(R.id.list);

        new AsyncTask<Void, Void, Void>() 
        {
            @Override
            protected void onPreExecute() 
            {
                pd = ProgressDialog.show(MainActivity.this,
                        "Loading..", "Please Wait", true, false);
            }// End of onPreExecute method

            @Override
            protected Void doInBackground(Void... params) 
            {
                getContacts();

                return null;
            }// End of doInBackground method

            @Override
            protected void onPostExecute(Void result)
            {
                pd.dismiss();
                CustomAdapter cus = new CustomAdapter(MainActivity.this);
               // ArrayAdapter<String>   arrayAdapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,aa);
             lvCallList.setAdapter(cus);

            }//End of onPostExecute method
        }.execute((Void[]) null);
    }
        private void getContacts()
        {
            ContentResolver cr = getContentResolver();
            Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null,null, null, null);
            if (cur.getCount() > 0)
            {
                while (cur.moveToNext())
                {
                    String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
                    String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

                    aa.add(name);
                    if (Integer.parseInt(cur.getString(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 phoneNumber = pCur.getString(pCur.getColumnIndex( ContactsContract.CommonDataKinds.Phone.NUMBER));
                            num.add(phoneNumber);
                        } 
                        pCur.close();
                    }
                }
            }
        }

        public class CustomAdapter extends BaseAdapter 
        {
            /*
             * Variables Declaration section
             */
            private Context mContext;

            public CustomAdapter(Context context) 
            {
                mContext = context;
            }//End of CustomAdapter constructor

            public int getCount() 
            {
                return aa.size();
            }//End of getCount method

            public Object getItem(int position) 
            {
                return position;
            }//End of getItem method

            public long getItemId(int position) 
            {
                return position;
            }//End of getItemId method

            public View getView(int position, View convertView, ViewGroup parent) 
            {
                ViewHolder holder;
                final int pos = position;

                if (convertView == null) 
                {
                    holder = new ViewHolder();

                    convertView = LayoutInflater.from(mContext).inflate(R.layout.display_contact, null);
                    holder.textviewName = (TextView) convertView.findViewById(R.id.textView1);
                    holder.textviewNumber = (TextView) convertView.findViewById(R.id.textView2);
                    holder.checkbox = (CheckBox) convertView.findViewById(R.id.checkBox1);

                    convertView.setTag(holder);
                }//End of if condition
                else
                {
                    holder = (ViewHolder) convertView.getTag();
                }//End of else

                holder.checkbox.setId(position);
                holder.textviewName.setId(position);
                holder.textviewNumber.setId(position);


                holder.textviewName.setText(aa.get(position));
                holder.textviewNumber.setText("No. "+num.get(position));

                holder.id = position;

                return convertView;
            }//End of getView method
        }//End of CustomAdapter instance inner class

        static class ViewHolder 
        {
            TextView textviewName;
            TextView textviewNumber;
            CheckBox checkbox;
            int id;
        }

}


回答2:

You can't touch views in Non-UI thread. You must set adapter in onPostExecute();

Use this: (Also, I hope that you keep your contacts somewhere, because I don't see contacts variable in your snippet)

new AsyncTask<Void, Void, Void>() 
{

    @Override
    protected void onPreExecute() 
    {
        pd = ProgressDialog.show(CallListActivity.this,
                "Loading..", "Please Wait", true, false);
    }// End of onPreExecute method

    @Override
    protected Void doInBackground(Void... params) 
    {
        getContacts();
        return null;
    }// End of doInBackground method

    @Override
    protected void onPostExecute(Void result)
    {
        arrayAdapter = new ArrayAdapter<String>(CallListActivity.this, R.layout.display_contacts,R.id.tv_single_contact_number,displayContactName);
        lvCallList.setAdapter(new CustomAdapter(CallListActivity.this));
        pd.dismiss();

    }//End of onPostExecute method
}.execute((Void[]) null);


回答3:

You are trying to call setAdapter in doInBackground which is not running on UI thread. You must pass the result of contact loading from doInBackground(..) to onPostExcecute(..) and there you can create a an adapter and set it in the list view.



回答4:

I found out the problem, I was trying to initialise count after setting adapter, that was the problem, Thanks stackoverflow and @Raghunandan

        protected void onPostExecute(Void result)
        {
            count = displayContactName.size();
            thumbnailsselection = new boolean[count];
            lvCallList.setAdapter(new CustomAdapter(CallListActivity.this));
            pd.dismiss();
        }//End of onPostExecute method