How to set filter for recycler view if search query resulting no match in search view

北城以北 提交于 2020-02-05 08:17:40

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!