SearchView 在 Android 中不起作用。为啥这样?

Posted

技术标签:

【中文标题】SearchView 在 Android 中不起作用。为啥这样?【英文标题】:SearchView not working in Android . Why So?SearchView 在 Android 中不起作用。为什么这样? 【发布时间】:2019-11-05 10:05:52 【问题描述】:

我在我的应用程序中使用带有标题的 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.适配器的构造函数是wong:this.list = list; this.listFiltered = list;,这使得listlistFiltered是同一个实例。您应该使它们成为不同的实例。尝试将其更改为:this.list.addAll(list); this.listFiltered = list;。 2.看起来你想要list作为完整数据,那么你显示的数据应该来自listFiltered,所以在onBindViewHolder中更改:ItemObject list = this.list.get(position);ItemObject list = this.listFiltered.get(position);希望对您有所帮助! 【参考方案1】:

如您所知,getPageName() 上存在 null 异常,所以请检查一下

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

我看到你在getItemCount() 中有list 对象,所以我假设主要的“列表”是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();
            

备份原始数据并放入过滤器

【讨论】:

` if(!row.getPageName()==null && !row.getPageName().isEmpty()) ` 这一行给了我错误运算符'!'不能应用于“java.lang.String” 我不好尝试这种方式if(row.getPageName()!=null... 现在当我点击搜索图标时,我的整个列表都消失了,什么也没有显示 搜索列表中的内容。或者你的数据列表有问题。记录 for 循环并打印 getPageName 以查看是否确实有名称。也将 log on where 输入 if 语句或不

以上是关于SearchView 在 Android 中不起作用。为啥这样?的主要内容,如果未能解决你的问题,请参考以下文章

我的Android进阶之旅------&gt;Android中ListView中嵌套(ListView)控件时item的点击事件不起作的问题解决方法

@font-face 在 Firefox 中不起作用 [重复]

AngularJS、SweetAlert.js 在自定义指令中不起作用

RecyclerView 的 SearchView 不起作用

SwipeRefreshLayout 在 Android 中不起作用

为啥 recyclerview 的 searchview 不起作用?