如何在使用 Livedata 时使用 Filter SearchView for RecyclerView?
How to use Filter SearchView for RecyclerView when using Livedata?
我有一个RecyclerView
。我想让它可以用 SearchView 过滤。我的申请基于 Android Architecture Components
.
我为 searchView
创建了一个过滤方法。当我搜索某些东西时它可以工作但是当我从 searchView
清除文本时,列表不会改变并且仍然显示搜索数据。
Activity:
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;
}
}
变化:
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();
}
};
}
并且不要忘记在适配器 class 中实现 Filterable
。
参考下面的答案会有帮助,
搜索文本将通过以下代码传递给 recyclerView。
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return true;
}
那么 RecyclerViewAdapter class 应该实现 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
}
}
};
}
我有一个RecyclerView
。我想让它可以用 SearchView 过滤。我的申请基于 Android Architecture Components
.
我为 searchView
创建了一个过滤方法。当我搜索某些东西时它可以工作但是当我从 searchView
清除文本时,列表不会改变并且仍然显示搜索数据。
Activity:
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;
}
}
变化:
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();
}
};
}
并且不要忘记在适配器 class 中实现 Filterable
。
参考下面的答案会有帮助, 搜索文本将通过以下代码传递给 recyclerView。
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return true;
}
那么 RecyclerViewAdapter class 应该实现 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
}
}
};
}