You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ViewPager中RecyclerView结合SearchView筛选显示内容异常问题

问题描述

在包含两个Fragment的ViewPager中,Fragment2内通过SearchView对RecyclerView进行数据筛选时出现异常:输入筛选内容后,RecyclerView显示的条目内容与预期不符,但点击条目弹出的Toast却能正确显示对应条目的名称。


RecyclerView适配器代码(带筛选功能)

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyviewHolder> implements Filterable {
    ListItemsBinding itembind;
    Context co;
    List<Items> mylist;
    List<Items> copy;

    public CustomAdapter(List<Items> mylist, Context co) {
        this.mylist = mylist;
        copy=new ArrayList<>(mylist);
        this.co = co;
    }

    @NonNull
    @Override
    public CustomAdapter.MyviewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(co);
        itembind= ListItemsBinding.inflate(inflater,parent,false);
        return new MyviewHolder(itembind);
    }


    @Override
    public void onBindViewHolder(@NonNull CustomAdapter.MyviewHolder holder, int position) {
        Items item = mylist.get(position);
        itembind.text.setText(item.getName());

    }

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

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    @Override
    public Filter getFilter() {
        return exampleFilter;
    }


    private final Filter exampleFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            List<Items> filteredList = new ArrayList<>();

            if (constraint == null || constraint.length() == 0) {
                filteredList.addAll(copy);
            } else {
                String filterPattern = constraint.toString().toLowerCase().trim();

                for (Items item : copy) {
                    if (item.getName().toLowerCase().contains(filterPattern)) {
                        filteredList.add(item);
                    }
                }
            }

            FilterResults results = new FilterResults();
            results.values = filteredList;

            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mylist.clear();
            mylist.addAll((List) results.values);
            notifyDataSetChanged();
        }
    };

    public class MyviewHolder extends RecyclerView.ViewHolder {


        public MyviewHolder(ListItemsBinding itembind) {
            super(itembind.getRoot());

            itembind.const1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(co,""+mylist.get(getAdapterPosition()).getName(),Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
}

Fragment2代码(已实现onCreateOptionsMenu)

public class Fragment2 extends Fragment {
   
    CustomAdapter adaptive;
    List<Items> mylist;
    Fragment2Binding filesbinding;
    Context context;

 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        filesbinding= FragmentVoiceRecordFilesBinding.inflate(inflater,container,false);
        context = getContext();
        return filesbinding.getRoot();

    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setdata();
        recycle();
    }

 public void recycle() {
                filesbinding.recycle.setHasFixedSize(true);
                RecyclerView.LayoutManager layout = new LinearLayoutManager(context);
                filesbinding.recycle.setLayoutManager(layout);
                filesbinding.recycle.scheduleLayoutAnimation();
                adaptive= new CustomAdapter(mylist,context);
                filesbinding.recycle.setAdapter(adaptive);
}

public void setdata() {
            mylist=new ArrayList<>();
            mylist.add(new Items("1"));
            mylist.add(new Items("2"));
            mylist.add(new Items("3"));
            mylist.add(new Items("4"));
        }

@Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        inflater.inflate(R.menu.search_menu, menu);
        MenuItem searchItem = menu.findItem(R.id.actionSearch);
        SearchView searchView = (SearchView) searchItem.getActionView();
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                 return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                adaptive.getFilter().filter(newText);
                return false;
            }
        });
        super.onCreateOptionsMenu(menu, inflater);
    }
}

searchmenu.xml代码

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/actionSearch"
        android:icon="@drawable/ic_baseline_search_24"
        android:title="Search"
        app:actionViewClass="androidx.appcompat.widget.SearchView"
        app:showAsAction="always|collapseActionView" />
</menu>

问题原因及修复方案

问题根源

适配器中的ListItemsBinding itembind是类成员变量,而非每个ViewHolder独立持有。当RecyclerView复用ViewHolder时,所有条目都会复用同一个binding实例,导致最后一次调用onBindViewHolder时设置的文本会覆盖之前所有条目的显示内容。而点击事件中是通过getAdapterPosition()从数据源mylist获取正确数据,所以Toast显示正常。

修复步骤

  1. 将适配器中的ListItemsBinding itembind改为onCreateViewHolder方法内的局部变量,不再作为类成员。
  2. 在MyviewHolder中持有自己的ListItemsBinding实例,确保每个条目有独立的绑定对象。
  3. 在onBindViewHolder中通过holder的binding来设置文本内容。

修改后的适配器代码:

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyviewHolder> implements Filterable {
    Context co;
    List<Items> mylist;
    List<Items> copy;

    public CustomAdapter(List<Items> mylist, Context co) {
        this.mylist = mylist;
        copy=new ArrayList<>(mylist);
        this.co = co;
    }

    @NonNull
    @Override
    public CustomAdapter.MyviewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(co);
        // 改为局部变量,每个ViewHolder创建独立的binding
        ListItemsBinding itembind= ListItemsBinding.inflate(inflater,parent,false);
        return new MyviewHolder(itembind);
    }


    @Override
    public void onBindViewHolder(@NonNull CustomAdapter.MyviewHolder holder, int position) {
        Items item = mylist.get(position);
        // 使用当前holder的binding设置文本
        holder.itembind.text.setText(item.getName());
    }

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

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    @Override
    public Filter getFilter() {
        return exampleFilter;
    }


    private final Filter exampleFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            List<Items> filteredList = new ArrayList<>();

            if (constraint == null || constraint.length() == 0) {
                filteredList.addAll(copy);
            } else {
                String filterPattern = constraint.toString().toLowerCase().trim();

                for (Items item : copy) {
                    if (item.getName().toLowerCase().contains(filterPattern)) {
                        filteredList.add(item);
                    }
                }
            }

            FilterResults results = new FilterResults();
            results.values = filteredList;

            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mylist.clear();
            mylist.addAll((List) results.values);
            notifyDataSetChanged();
        }
    };

    public class MyviewHolder extends RecyclerView.ViewHolder {
        // ViewHolder持有自己的binding实例
        ListItemsBinding itembind;

        public MyviewHolder(ListItemsBinding itembind) {
            super(itembind.getRoot());
            this.itembind = itembind;

            itembind.const1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(co,""+mylist.get(getAdapterPosition()).getName(),Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
}

内容的提问来源于stack exchange,提问作者A.G

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 07:54:19