【问题标题】:How to use Filter SearchView for RecyclerView when using Livedata?使用 Livedata 时如何为 RecyclerView 使用 Filter SearchView?
【发布时间】:2020-01-01 07:39:19
【问题描述】:

我有一个RecyclerView。我想使用 SearchView 使其可过滤。我的申请基于Android Architecture Components

我为searchView 创建了一个过滤方法。当我搜索某些内容时,它可以工作,但是当我从searchView 中清除文本时,列表不会改变并且仍然显示搜索数据。

活动:

    private StudentAdapter mAdapter;

    mAdapter = new StudentAdapter(this);
    recyclerView.setAdapter(mAdapter);

    //ViewModel
    StudentViewModelFactory factory = new StudentViewModelFactory(mDb, mClassId);
    StudentViewModel viewModel = ViewModelProviders.of(this, factory).get(StudentViewModel.class);
    viewModel.getStudentEntries().observe(this, studentEntries -> mAdapter.setStudents(studentEntries));

    //SearchView
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
    @Override
    public boolean onQueryTextSubmit(String query){
            return false;
    }

    @Override
    public boolean onQueryTextChange(String newText){
            mAdapter.getFilter().filter(newText);
            return false;
    }
    });

适配器:

public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.itemHolder> {

    private List<StudentEntry> mStudentEntries;
    private List<StudentEntry> filteredStudentEntries;

    public StudentAdapter(Context context) {
        this.context = context;
    }

    public void setStudents(List<StudentEntry> studentEntries) {
        this.mStudentEntries = studentEntries;
        notifyDataSetChanged();
    }

    public void setPerformances(List<PerformanceEntry> performanceEntries) {
        this.mPerformanceEntries = performanceEntries;
        notifyDataSetChanged();
    }
        .
        .
        .

    public Filter getFilter() {
        return new Filter() {
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                mStudentEntries = (List<StudentEntry>) results.values;
                notifyDataSetChanged();
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                filteredStudentEntries = null;//avaz shod vali test nashod
                if (constraint.length() == 0) {
                    filteredStudentEntries = mStudentEntries;
                } else {
                    filteredStudentEntries = getFilteredResults(constraint.toString().toLowerCase());
                }


                FilterResults results = new FilterResults();
                results.values = filteredStudentEntries;
                return results;
            }
        };
    }

    protected List<StudentEntry> getFilteredResults(String constraint) {
        List<StudentEntry> results = new ArrayList<>();

        for (StudentEntry item : mStudentEntries) {
            if (item.getStudentName().toLowerCase().contains(constraint)
                    || item.getStudentId().toLowerCase().contains(constraint)) {
                results.add(item);
            }
        }
        return results;
    }
}

【问题讨论】:

标签: android android-recyclerview searchview android-livedata android-viewmodel


【解决方案1】:

更改:

private List<StudentEntry> filteredStudentEntries;

收件人:

private ArrayList<StudentEntry> arrayList = new ArrayList<>();

而改变:

public void setStudents(List<StudentEntry> studentEntries) {
    this.mStudentEntries = studentEntries;
    notifyDataSetChanged();
}

到:

public void setStudents(List<StudentEntry> studentEntries) {
    this.mStudentEntries = studentEntries;
    arrayList.addAll(mStudentEntries);
    notifyDataSetChanged();
}

并更改过滤方法:

@Override
public Filter getFilter() {
    return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {

            constraint = constraint.toString().toLowerCase().trim();
            mStudentEntries.clear();
            if (constraint.length() == 0) {
                mStudentEntries.addAll(arrayList);
            } else {
                for (StudentEntry item : arrayList) {
                    if (item.getStudentName().toLowerCase(Locale.getDefault()).contains(constraint)
                            || item.getStudentId().toLowerCase(Locale.getDefault()).contains(constraint)) {
                        mStudentEntries.add(item);
                    }
                }
            }

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

            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            notifyDataSetChanged();
        }
    };
}

别忘了在适配器类中实现Filterable

【讨论】:

  • 检查我的编辑,我正在处理这个。请记住在您的Adapter 中实现Filterable。我希望我已经为您的案例正确更改了代码(表名)。
  • 你的方法也行不通,我的问题是我从LiveData 获取列表,所以在更改它@SkypeDogg 后我无法访问列表
  • 您有两个列表。一个包含您的所有数据,第二个保留搜索结果。每次您搜索某些内容时,您都在 List 1(包含所有数据)上执行此操作,然后将结果复制到 List2。这意味着其中一个(List1)始终具有相同的数据,而第二个在您每次搜索时都会更改。我发现只有filteredStudentEntries = mStudentEntries; 在那里你只是复制你的列表的引用,这意味着你使用同一个列表。如果您清除 search view 列表中的 size() 为 0,然后触发 if 并且它正在复制对 List1 的引用,然后您就可以使用它
  • myIssueList 是什么意思?
  • 我找到了解决方案(需要一个稳定的列表)并编辑您的答案。谢谢您的帮助。 @SkypeDogg
【解决方案2】:

请参考以下答案,它会有所帮助, 搜索文本将通过以下代码传递给 recyclerView。

 @Override
    public boolean onQueryTextChange(String newText) {
        adapter.getFilter().filter(newText);
        return true;
    }

那么 RecyclerViewAdapter 类应该实现 Filterable

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

//constructor loads data to dataList
      DashboardRecyclerViewAdapter(ArrayList<Object> data,Context context)
     {
            this.context = context;
            this.dataList = data;   
            this.filteredDataList = new ArrayList<>(data.size());
            this.filteredDataList.addAll(dataList);
        }

    //override this method, it gets the SerchText and then compares with dataList
    @Override
        public Filter getFilter() {
            return new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence charSequence) {
                    ArrayList<Object> filteredDataList_temp = new ArrayList<>();
                    String charString = charSequence.toString().toLowerCase();

                    if (charString.isEmpty() || charString.trim().length() == 0 ) {
                        filteredDataList_temp = dataList;
                    } else {
                        for (Object row : dataList) {
                            FoodDetail r = (FoodDetail) row;
                            if (foodName.contains(charString)) {
                                    filteredDataList_temp.add(row);

                                }
                            }
                        }


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


               @Override
                protected void publishResults(CharSequence constraint, FilterResults results) {

                    if (filteredDataList != null) {
                        filteredDataList.clear();
                        filteredDataList.addAll((ArrayList<Object>) results.values);
                        notifyDataSetChanged();   //once completed Then RecyclerView updated with only searched List
                    }

                }
            };

    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-17
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    • 2015-04-26
    • 2016-10-29
    • 2020-12-05
    相关资源
    最近更新 更多