RecyclerView(自定义适配器)不刷新搜索列表
Posted
技术标签:
【中文标题】RecyclerView(自定义适配器)不刷新搜索列表【英文标题】:RecyclerView (Custom Adapter) not refreshing the List on search 【发布时间】:2021-10-12 09:37:15 【问题描述】:这是我在 *** 上的第一个问题。我最近才开始进行 android 开发。
我想做的事:
我有一个人员列表,我想根据用户在我的工具栏(不是 ActionBar)的搜索框中的输入来过滤/搜索 RecyclerView(使用自定义适配器)列表 (Initial List)。
我的问题:
最初,什么都没有发生。这份名单根本没有改变。现在,列表发生了变化,但无论输入什么,都只会显示一个固定列表项(Current Search output)。我的回收器适配器没有刷新到新的过滤列表。而且我在 bulid 或 logcat 中没有收到任何错误。
我尝试过的:
经过一整天的调试,并在我的布局管理器和 RecycleView 适配器中修复了一些“NullPointerExceptions”,并尝试了 2 种不同的过滤方法。即使我能够生成filtered array (List values in Logcat),我也无法得到结果。我尝试使用“notifyDataSetChanged()”、“notifyItemRangeChanged()”和“*notifyAll();,但都是徒劳的......
请帮忙.....
公共类 MainActivity 扩展 AppCompatActivity
ArrayList<Consultant> consultants= new ArrayList<>();
ArrayList<Consultant> allConsultants = new ArrayList<>();
int rating=5;
int price = 10000;
String categoryFilter;
String ratingFilter;
RecyclerView recyclerView;
Consultant_RecyclerAdapter.RecyclerViewClickListener listener;
Consultant_RecyclerAdapter adapter= new Consultant_RecyclerAdapter(consultants,listener);
Spinner s_categories;
Spinner s_rating;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
recyclerView= findViewById(R.id.RecycleView);
s_categories=findViewById(R.id.Spinner_Category);
s_rating=findViewById(R.id.Spinner_Rating);
addToList();
setUpAdapter();
private void setUpAdapter()
Log.i("Adapter","Started");
setOnClickListener();
Consultant_RecyclerAdapter adapter = new Consultant_RecyclerAdapter(consultants,listener);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
Log.i("Adapter","Ended");
private void addToList()
consultants.add(new Consultant("Dr Kapoor", "consultant_id", "profilePic_src", new String[]"Dentist","Dermatology", 1000, 5));
consultants.add(new Consultant("Dr Pankaj Kumar", "consultant_id", "profilePic_src", new String[]"Psychology","Respiratory", 3000, 1));
consultants.add(new Consultant("Dr Harsh Jha", "consultant_id", "profilePic_src", new String[]"Internal Medicine", 1500, 5));
consultants.add(new Consultant("Dr Gaurav Singh", "consultant_id", "profilePic_src", new String[]"Dentist","Cardiologist", 3500, 4));
consultants.add(new Consultant("Dr Aman", "consultant_id", "profilePic_src", new String[]"Lungs","Neuro", 1000, 2));
consultants.add(new Consultant("Dr Jatin Chabra", "consultant_id", "profilePic_src", new String[]"Psychology", 5000, 3));
Log.i("List","Done");
allConsultants=new ArrayList<>(consultants);
private void setOnClickListener()
listener = new Consultant_RecyclerAdapter.RecyclerViewClickListener()
@Override
public void onClick(View v, int position)
Intent intent = new Intent(getApplicationContext(), ConsultantProfileActivity.class);
intent.putExtra("consultant_name", consultants.get(position).getName());
intent.putExtra("pic_src", consultants.get(position).getProfilePic_src());
intent.putExtra("about", consultants.get(position).getAbout());
intent.putExtra("consultant_id",consultants.get(position).getConsultant_id());
intent.putExtra("categories",consultants.get(position).getCategories());
startActivity(intent);
;
@Override
public boolean onCreateOptionsMenu(Menu menu)
getMenuInflater().inflate(R.menu.search, menu);
MenuItem menuItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) menuItem.getActionView();
searchView.setQueryHint("Search....");
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
@Override
public boolean onQueryTextSubmit(String query)
return false;
@Override
public boolean onQueryTextChange(String newText)
Log.i("Search","QueryChanged");
//adapter.getFilter().filter(newText);
filter(newText);
return false ;
);
return true;
private void filter(String text)
// creating a new array list to filter our data.
ArrayList<Consultant> filteredlist = new ArrayList<>();
// running a for loop to compare elements.
for (Consultant item : allConsultants)
Log.i("Filter: ",item.getName()+"...."+text);
// checking if the entered string matched with any item of our recycler view.
if (item.getName().toLowerCase().contains(text.toLowerCase()))
Log.i("Match","Found");
// if the item is matched we are
// adding it to our filtered list.
filteredlist.add(item);
Log.i("Filter: ",(filteredlist.toString()));
if (filteredlist.isEmpty())
// if no item is added in filtered list we are
// displaying a toast message as no data found.
Toast.makeText(this, "No Data Found..", Toast.LENGTH_SHORT).show();
else
// at last we are passing that filtered
// list to our adapter class.
adapter.filterList(filteredlist);
请忽略下面Recycler Adapter中的搜索方式,我目前正在使用mainActivity中的搜索方式
公共类 Consultant_RecyclerAdapter 扩展 RecyclerView.Adapter
private RecyclerViewClickListener listener;
public Consultant_RecyclerAdapter(ArrayList<Consultant> consultants, RecyclerViewClickListener listener)
this.consultants = consultants;
this.listener = listener;
//AllConsultants = new ArrayList<>(consultants);
//preFilteredList = new ArrayList<>(consultants);
//NOTIFYING THE ADAPTER ABOUT UPDATE
public void filterList(ArrayList<Consultant> filteredlist)
consultants.clear();
consultants.addAll(filteredlist);
notifyDataSetChanged();
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
private TextView name, rating, price, category;
private ImageView profile;
public MyViewHolder(@NonNull View view)
super(view);
name = view.findViewById(R.id.textView_Name);
profile = view.findViewById(R.id.imageView_ProfilePic);
category = view.findViewById(R.id.textView_Category);
rating = view.findViewById(R.id.textView_Rating);
price = view.findViewById(R.id.textView_Price);
view.setOnClickListener(this);
@Override
public void onClick(View view) listener.onClick(view, getAdapterPosition());
@NonNull
@Override
public Consultant_RecyclerAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.consultant_list_item, parent, false);
return new MyViewHolder(itemView);
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position)
String name = consultants.get(position).getName();
String profilePic_src = consultants.get(position).getProfilePic_src();
float rating = consultants.get(position).getRating();
String categories = "";
//Converting Array to string
for (String i : consultants.get(position).getCategories())
categories = i + ", " + categories;
int price = consultants.get(position).getPrice();
holder.name.setText(name);
holder.category.setText(categories);
holder.price.setText(String.valueOf(price));
holder.rating.setText(String.valueOf(rating));
holder.profile.setImageResource(R.drawable.consultant);
@Override
public int getItemCount()
return consultants.size();
public interface RecyclerViewClickListener
void onClick(View v, int position);
public void listUpdate(String categoryFilter, String ratingFilter)
preFilteredList = new ArrayList<>();
if (categoryFilter != null || ratingFilter != null)
for (Consultant item : AllConsultants)
if (String.valueOf(item.getRating()).toLowerCase(Locale.ROOT).contains(ratingFilter) && item.getCategories().toString().toLowerCase(Locale.ROOT).contains(categoryFilter))
preFilteredList.add(item);
else
preFilteredList= new ArrayList<Consultant>(AllConsultants);
consultants.clear();
consultants.addAll(preFilteredList);
getFilter();
@Override
public Filter getFilter()
return theFilter;
public Filter theFilter = new Filter()
@Override
protected FilterResults performFiltering(CharSequence constraint)
List<Consultant> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0)
filteredList.addAll(AllConsultants);
else
String filterPattern = constraint.toString().toLowerCase().trim();
for (Consultant item : AllConsultants)
Log.i("Filter: ",item.getName()+"...."+filterPattern);
if (item.getName().toLowerCase().contains(filterPattern))
Log.i("Match","Found");
filteredList.add(item);
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
Log.i("Filter ","Published");
consultants.clear();
consultants.addAll((List) results.values);
notifyDataSetChanged();
;
【问题讨论】:
【参考方案1】:不要使用活动来过滤结果,这会降低性能。在 Adapter 中使用 Filterable 接口,它在后台线程上执行过滤并将结果发布到主线程上。我看到你已经实现了。
通过查看您的适配器代码,我认为它应该可以工作,因为您维护了两个列表 complete
和 filtered
的不同引用。
我的罪魁祸首是您已将适配器初始化为全局变量,但您设置为 RecyclerView
的适配器是您在本地创建的另一个适配器。解决这个问题,它应该可以工作。
private Consultant_RecyclerAdapter adapter ; // Global variable
private void setUpAdapter()
Log.i("Adapter","Started");
setOnClickListener();
adapter = new Consultant_RecyclerAdapter(consultants,listener);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
Log.i("Adapter","Ended");
【讨论】:
刚刚试过这个。错误:java.lang.NullPointerException: at java.util.ArrayList.addAll(ArrayList.java:588) at (Consultant_RecyclerAdapter.java:157) Consultant_RecyclerAdapter.java:157=> advisors.addAll((List) results.values); RecyclerView 适配器中的最后 6 行。我是android dev的新手,如果您能进一步指导我,那将非常有帮助 尝试将适配器中的consulatant
ArrayList 设置为私有/公共。还是不行以上是关于RecyclerView(自定义适配器)不刷新搜索列表的主要内容,如果未能解决你的问题,请参考以下文章
notifyDataSetChange 不适用于 RecyclerView [重复]
Android:重新绑定 ListView 或 RecyclerView 而不刷新 Header
支持下拉刷新和上划加载更多的自定义RecyclerView(仿XListView效果)