1

This code works fine if the item we entered in search view matches but if we enter some query which does not match ...application is crashing in android.

Here Main_ATMItemList is the list in which whole list of results are returned. Please help me what I need to add so that the code works even the query does not match.

I have created this method in adapter class

public void setFilter(String queryText) {
        visibleObjects = new ArrayList<>();

            for (RouteByATMList.Route_ATM item : Main_ATMItemList) {
                if (item.ATMNumber.startsWith(queryText))
                {
                    visibleObjects.add(item);

                }
            }
        }

        notifyDataSetChanged();
        Log.e("dataset changed","dataset changed");
    }
Ravi Yadav
  • 2,296
  • 3
  • 25
  • 32
  • you can use continue if query doesnot match inside for loop – Ali Kazmi Feb 05 '15 at 05:45
  • you are saying I have to create else and then add continue? – Ravi Yadav Feb 05 '15 at 05:54
  • yeah, exactly I mean that – Ali Kazmi Feb 05 '15 at 05:55
  • I have done exactly but what happens is when I put toast inside else then it is again going in the for loop for every entry and toast keep on displaying – Ravi Yadav Feb 05 '15 at 05:56
  • i need to test before entering inside for loop...can u suggest something – Ravi Yadav Feb 05 '15 at 05:58
  • I will be doing so,display toast and will go for next comparison; and again if query does not match it will display toast. For now, What I understood is its better to write else block with just single continue statement in it because you are not doing anything if query does not match. just continue and let it go for next comaprision – Ali Kazmi Feb 05 '15 at 06:00

2 Answers2

2

You need to abstract RecyclerView.Adapter and make it inherit Filterable. Then you subclass this abstraction to the adapter you want to create.

Override getFilter() method to instantiate Filter. Refer to examples how to filter an adapter and move the logic you have now, in performFiltering(String constraint) method of the Filter

You should do the filtering in background thread, hence the Filterable. Filterable does the filtering on background thread and delivers the result on UI thread or thread that called filtering.

Like this you can achieve somewhat of compatibility to old good ListView.

Someone in the comments asked for example:

public abstract class BaseFilterableRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> implements Filterable {

    private Context mContext;
    public BaseFilterableRecyclerViewAdapter(Context context) {
        this.mContext = context;
    }
    public abstract void sort(SortingFilter.Sort sortingStrategy);

}

In the extended class:

public class ProductAdapter extends BaseFilterableRecyclerViewAdapter<RecyclerView.ViewHolder>{

//------- Other methods ----

    @Override
    public Filter getFilter() {
        return new SortingFilter(mData) {
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                if (results.values != null) {
                    int last = mData.size();
                    mData = (List<? extends Product>) results.values;
                    notifyItemRangeChanged(mHeaderView == null ? 0 : 1, last);
                }
            }
        };
    }


}
Nikola Despotoski
  • 49,966
  • 15
  • 119
  • 148
0

Use this works for me all time

private List<ExampleModel> filter(List<ExampleModel> models, String query) {
    query = query.toLowerCase();

    final List<ExampleModel> filteredModelList = new ArrayList<>();
    for (ExampleModel model : models) {
        final String text = model.getText().toLowerCase();
        if (text.contains(query)) {
            filteredModelList.add(model);
        }
    }
    return filteredModelList;
}

Then onQueryTextChange(String query) call the filter

final List<ExampleModel> filteredModelList = filter(mModels, query);
        mAdapter.animateTo(filteredModelList);
        mRecyclerView.scrollToPosition(0);

below is the animateTo method found in the Adapter

 public void animateTo(List<ExampleModel> models) {
        applyAndAnimateRemovals(models);
        applyAndAnimateAdditions(models);
        applyAndAnimateMovedItems(models);
    }

private void applyAndAnimateRemovals(List<ExampleModel> newModels) {
    for (int i = mModels.size() - 1; i >= 0; i--) {
        final ExampleModel model = mModels.get(i);
        if (!newModels.contains(model)) {
            removeItem(i);
        }
    }
}

private void applyAndAnimateAdditions(List<ExampleModel> newModels) {
    for (int i = 0, count = newModels.size(); i < count; i++) {
        final ExampleModel model = newModels.get(i);
        if (!mModels.contains(model)) {
            addItem(i, model);
        }
    }
}

private void applyAndAnimateMovedItems(List<ExampleModel> newModels) {
    for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) {
        final ExampleModel model = newModels.get(toPosition);
        final int fromPosition = mModels.indexOf(model);
        if (fromPosition >= 0 && fromPosition != toPosition) {
            moveItem(fromPosition, toPosition);
        }
    }
}

public ExampleModel removeItem(int position) {
    final ExampleModel model = mModels.remove(position);
    notifyItemRemoved(position);
    return model;
}

public void addItem(int position, ExampleModel model) {
    mModels.add(position, model);
    notifyItemInserted(position);
}

public void moveItem(int fromPosition, int toPosition) {
    final ExampleModel model = mModels.remove(fromPosition);
    mModels.add(toPosition, model);
    notifyItemMoved(fromPosition, toPosition);
}

}

muchbeer
  • 16
  • 3
  • You can also check http://stackoverflow.com/questions/30398247/how-to-filter-a-recyclerview-with-a-searchview – muchbeer Aug 02 '15 at 22:44