SearchView не работает в Android. Почему так? - PullRequest
0 голосов
/ 23 июня 2019

Я использую Recycleview с заголовками в моем приложении, и я пытаюсь реализовать searchview в моем приложении, но это не работает. Когда я нажимаю на вид поиска и набираю что-то, результаты не фильтруются, и я получаю это в своем журнале регистрации.

2019-06-23 14:00:48.471 27193-27508/com.example.testapp W/Filter: An exception occured during performFiltering()!
    java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.toLowerCase()' on a null object reference
        at com.example.testapp.TitleAdapter$1.performFiltering(TitleAdapter.java:92)
        at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:171)
        at android.os.HandlerThread.run(HandlerThread.java:65)

Я занимаюсь этим часами и не могу понять, что я делаю не так. Вот мой адаптер.

public class TitleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable {

    private static final int TYPE_HEADER = 0;
    private static final int TYPE_ITEM = 1;
    private List <ItemObject> list;
    private List <ItemObject> listFiltered;
    private Context context;

    public TitleAdapter(Context context, List <ItemObject> list) {
        this.context = context;
        this.list = list;
        this.listFiltered = list;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (viewType == TYPE_HEADER) {
            View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_layout, parent, false);
            return new HeaderViewHolder(layoutView);
        } else if (viewType == TYPE_ITEM) {
            View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
            return new ItemViewHolder(layoutView);
        }
        throw new RuntimeException("No match for " + viewType + ".");
    }

    @Override
    public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
        ItemObject list = this.list.get(position);
        if (holder instanceof HeaderViewHolder) {
            ((HeaderViewHolder) holder).headerTitle.setText(list.getHeaderTitle());
        } else if (holder instanceof ItemViewHolder) {

            ((ItemViewHolder) holder).titleText.setText(list.getPageName());
        }
    }

    public ItemObject getItem(int position) {
        return list.get(position);
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    @Override
    public int getItemViewType(int position) {
        if (isPositionHeader(position))
            return TYPE_HEADER;
        return TYPE_ITEM;
    }

    private boolean isPositionHeader(int position) {
        ItemObject mObject = list.get(position);
        return mObject.isHeader();
    }

    @Override
    public Filter getFilter() {

        return new Filter() {
            protected FilterResults performFiltering(CharSequence constraint) {

                if (constraint == null || constraint.length() == 0){
                    listFiltered = list;
                } else {
                    String filterPattern = constraint.toString().toLowerCase().trim();
                    List<ItemObject> lstFilter = new ArrayList<>();
                    for (ItemObject row : list) {

                        // name match condition. this might differ depending on your requirement
                        // here we are looking for name or phone number match
                        if (row.getPageName().toLowerCase().contains(filterPattern)) {
                            lstFilter.add(row);
                        }
                    }

                    listFiltered = lstFilter;
                }

                FilterResults filterResults = new FilterResults();
                filterResults.values = listFiltered;
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults results) {
                listFiltered = (List <ItemObject>) results.values;
                // refresh the list with filtered data
                notifyDataSetChanged();
            }
        };

    }

    public class HeaderViewHolder extends RecyclerView.ViewHolder {
        TextView headerTitle;

        public HeaderViewHolder(View itemView) {
            super(itemView);
            headerTitle =  itemView.findViewById(R.id.headerText);

        }
    }

    public class ItemViewHolder extends RecyclerView.ViewHolder{

        TextView titleText;

        public ItemViewHolder(View itemView) {
            super(itemView);
            titleText = itemView.findViewById(R.id.titleText);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    int position = getAdapterPosition();

                    Intent intent = new Intent(context, ViewerActivity.class);
                    intent.putExtra("PageName",list.get(position).getPageName());
                    intent.putExtra("PageUrl",list.get(position).getPageUrl());
                    context.startActivity(intent);
                }
            });
        }
    }
}

Кстати, если вам интересно, это строка 92

 if (row.getPageName().toLowerCase().contains(filterPattern)) {
                            lstFilter.add(row);
                        }

1 Ответ

0 голосов
/ 23 июня 2019

Как вы знаете, getPageName() исключение null, поэтому просто отметьте его

if(row.getPageName()!=null && !row.getPageName().isEmpty())
 if (row.getPageName().toLowerCase().contains(filterPattern)) {
                            lstFilter.add(row);
                        }

и я вижу, что у вас есть list объект в getItemCount(), поэтому я предполагаю, что основной "Список" равен list, поэтому вам нужно выполнить резервное копирование этого, и в этой строке выполните следующее:

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults results) {
                //listFiltered = (List <ItemObject>) results.values;
                //back up `list` some where else for reloading the list without filter
                list.clear();
                list.addAll((List <ItemObject>) results.values);

                // refresh the list with filtered data
                notifyDataSetChanged();
            }

создайте резервную копию первичных данных и вставьте фильтр в

...