问题
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");
}
回答1:
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);
}
}
};
}
}
回答2:
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);
}
}
来源:https://stackoverflow.com/questions/28336920/how-to-set-filter-for-recycler-view-if-search-query-resulting-no-match-in-search