Show new ListView when the current listView gets empty

Ask by : Ankush January 12, 2014 11:14

In my app,I'm reading the contacts from the phonebook of the user and performs some action based on what the user wants. The activity in which the contacts are imported from the user's phonebook also contains an editText field which the user can use to filter the contacts and search through them. The code is as follows:

public class InviteFriendsFromContactsActivity extends Activity implements
    TextWatcher {

private EditText friendSearch;

private ArrayList<ContactInfo> contacts;

private ListView contactsListView;

private ContactsListviewAdapter clvAdapter;

public void onCreate(Bundle savedInstanceState) {

    friendSearch = (EditText) findViewById(;

    contactsListView = (ListView) findViewById(;



void ReadContacts() {

    contacts = new ArrayList<ContactInfo>();

    Cursor cursor = getContentResolver().query(
            ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
    while (cursor.moveToNext()) {
        long contactId = cursor.getLong(cursor
        String name = cursor.getString(cursor
        Cursor emails = getContentResolver().query(
                ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = "
                        + contactId, null, null);
        while (emails.moveToNext()) {
            // This would allow to get several email addresses, so if 1
            // contact has 2 emails, will be listed as 2 rows
            String emailAddress = emails
            if (emailAddress != null)
                contacts.add(new ContactInfo(contactId, name, emailAddress));

    clvAdapter = new ContactsListviewAdapter(getApplicationContext(),



public void onTextChanged(CharSequence s, int start, int before, int count) {
    if (clvAdapter != null) {
    if (clvAdapter.getCount() == 0) {
        ListView list = (ListView) findViewById(;

        final List<ContactInfo> listItems = new ArrayList<ContactInfo>();
        listItems.add(new ContactInfo("No results", ""));

        ContactsListviewAdapter adapter = new ContactsListviewAdapter(
                InviteFriendsFromContactsActivity.this, listItems) {

            public View getView(int position, View convertView,
                    ViewGroup viewGroup) {
                ContactInfo entry = listItems.get(position);

                CheckBox checkBox;
                TextView nameText;
                TextView emailText;

                LayoutInflater inflater = (LayoutInflater) InviteFriendsFromContactsActivity.this
                convertView = inflater.inflate(R.layout.row, null);

                nameText = (TextView) convertView

                emailText = (TextView) convertView

                checkBox = (CheckBox) convertView



                return convertView;


Also, my ContactsListViewAdapter class is as follows. This is a pretty big class but the part that I think is most relevant to this question is getFilter method.

class ContactsViewHolder {

public ContactsViewHolder(TextView nameTextView, TextView emailTextView,
        CheckBox checkBox, ImageView iv) {
    this.nameTextView = nameTextView;
    this.emailTextView = emailTextView;
    this.checkBox = checkBox;
    this.iv = iv;

public TextView getNameTextView() {
    return nameTextView;

public void setNameTextView(TextView nameTextView) {
    this.nameTextView = nameTextView;

public TextView getEmailTextView() {
    return emailTextView;

public void setEmailTextView(TextView emailTextView) {
    this.emailTextView = emailTextView;

public CheckBox getCheckBox() {
    return checkBox;

public void setCheckBox(CheckBox checkBox) {
    this.checkBox = checkBox;

public ImageView getIv() {
    return iv;

public void setIv(ImageView iv) {
    this.iv = iv;

private TextView nameTextView;
private TextView emailTextView;
private CheckBox checkBox;
private ImageView iv;


public class ContactsListviewAdapter extends BaseAdapter implements Filterable {
private Context context;

private List<ContactInfo> contacts;

private List<ContactInfo> originalContacts;

private List<String> selectedEmails = new ArrayList<String>();

public ContactsListviewAdapter(Context context, List<ContactInfo> contacts) {
    this.context = context;
    this.contacts = contacts;

public int getCount() {
    return contacts.size();

public Object getItem(int position) {
    return contacts.get(position);

public long getItemId(int position) {
    return position;

public View getView(int position, View convertView, ViewGroup viewGroup) {
    ContactInfo entry = contacts.get(position);

    CheckBox checkBox;
    TextView nameText;
    TextView emailText;
    ImageView contactPic;

    if (convertView == null) {
        LayoutInflater inflater = (LayoutInflater) context
        convertView = inflater.inflate(R.layout.row, null);

        nameText = (TextView) convertView.findViewById(;

        emailText = (TextView) convertView.findViewById(;

        contactPic = (ImageView) convertView.findViewById(;

        checkBox = (CheckBox) convertView

        // Optimization: Tag the row with it's child views, so we don't have
        // to
        // call findViewById() later when we reuse the row.
        convertView.setTag(new ContactsViewHolder(nameText, emailText,
                checkBox, contactPic));

        // If CheckBox is toggled, update the planet it is tagged with.
        checkBox.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                CheckBox cb = (CheckBox) v;
                ContactInfo contact = (ContactInfo) cb.getTag();

    // Reuse existing row view
    else {
        // Because we use a ViewHolder, we avoid having to call
        // findViewById().
        ContactsViewHolder viewHolder = (ContactsViewHolder) convertView
        checkBox = viewHolder.getCheckBox();
        nameText = viewHolder.getNameTextView();
        emailText = viewHolder.getEmailTextView();
        contactPic = viewHolder.getIv();

    // Tag the CheckBox with the Contact it is displaying, so that we can
    // access the Contact in onClick() when the CheckBox is toggled.

    // Display contact data

    Bitmap bitmap = People.loadContactPhoto(context,
            ContentUris.withAppendedId(People.CONTENT_URI, entry.getId()),
            R.drawable.contacts, null);

    return convertView;

public Filter getFilter() {
    Filter filter = new Filter() {

        protected void publishResults(CharSequence constraint,
                FilterResults results) {

            contacts = (List<ContactInfo>) results.values; // has the filtered values
            notifyDataSetChanged(); // notifies the data with new filtered values

        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults(); // Holds the
                                                            // results of a
                                                            // filtering
                                                            // operation in
                                                            // values
            List<ContactInfo> FilteredArrList = new ArrayList<ContactInfo>();

            if (originalContacts == null) {
                originalContacts = new ArrayList<ContactInfo>(contacts); 

             * If constraint(CharSequence that is received) is null returns
             * the mOriginalValues(Original) values else does the Filtering
             * and returns FilteredArrList(Filtered)
            if (constraint == null || constraint.length() == 0) {

                // set the Original result to return
                results.count = originalContacts.size();
                results.values = originalContacts;
            } else {
                constraint = constraint.toString().toLowerCase();
                for (int i = 0; i < originalContacts.size(); i++) {
                    String name = originalContacts.get(i).getName();
                    if (name.toLowerCase()
                            .startsWith(constraint.toString())) {
                // set the Filtered result to return
                results.count = FilteredArrList.size();
                results.values = FilteredArrList;
            return results;
    return filter;

public List<String> getSelectedEmails() {
    return selectedEmails;

The contacts are imported in the activity just fine. The problem occurs when I try to search the contacts. When I type 'x' in the search field (there are no contacts in my phonebook starting with x) there are 0 contacts displayed but the message No results found is not displayed. It will only be displayed after I type another letter after 'x'. In general, the message No results found is always displayed 1 letter after it actually should.

What is wrong and how is the message getting delayed?

View original question

Answer by : LuksprogNovember 04, 2012 16:34

Without looking to much at your code, I would say that the reason for that delay is the way you setup the filtering in the onTextChanged method. The filtering in the adapter is done in a background thread(the performFiltering runs on that thread) and the adapter doesn't see the new values, the results of the filtering, until the method publishResults(which runs on the main UI thread) is called.

Now, in the onTextchanged you call the filter method with the constraint and then immediately you re-set the same adapter on the ListView(why would you do something like this?!). By the time you get to the test if (clvAdapter.getCount() == 0) the filtering most likely didn't finished and your adapter still has the old values so the if test fails and you don't see the adapter that you set there with the No results found text. When you would enter another letter, the onTextChanged method will be called again and this time the adapter is indeed empty in that if condition will be true.

Cleanup the onTextchanged method(to only call filter) and try to implement that special row directly in the adapter.

View original answer