RecyclerView搜索功能异常:输入后列表消失的解决方法
解决RecyclerView搜索过滤条目消失的问题
我帮你排查了代码里的几个关键问题,这就是输入内容时RecyclerView条目消失、无法得到过滤结果的核心原因:
1. 搜索过滤的循环逻辑完全错误
你在onTextChanged里创建了空的filter集合,然后循环filter.size()——这时候filter是空的,循环根本不会执行,所以filter一直是空列表,RecyclerView自然显示空内容!应该遍历原始数据集合current,而不是刚创建的空filter。
2. 嵌套Volley请求的数据填充时机&变量错误
你在外部请求里把c添加到current后,嵌套的请求才异步返回设置name,这会导致初始列表的数据不完整;而且代码里c.setName(name);的name变量未定义,应该是获取到的foodie_name。
3. 不必要的重复设置LayoutManager
每次输入文本都重新设置LinearLayoutManager完全没必要,应该在Fragment初始化时设置一次即可。
修改后的代码示例
首先修正搜索监听的逻辑:
private void addTextListener() { search.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { String searchText = s.toString().toLowerCase().trim(); ArrayList<CurrentEntry> filterList = new ArrayList<>(); // 遍历原始数据集合current,而不是空的filter! for (CurrentEntry entry : current) { // 这里根据你实际要匹配的字段调整,比如entry的name属性 String entryText = entry.getName().toLowerCase(); if (entryText.contains(searchText)) { filterList.add(entry); } } // 直接更新adapter数据,无需重复设置LayoutManager if (adapt != null) { adapt.setFilteredList(filterList); // 推荐用adapter内部过滤方法 } else { adapt = new NewAdapter(filterList, getActivity()); recyclerView.setAdapter(adapt); } } @Override public void afterTextChanged(Editable s) { } }); }
然后修正Volley数据请求的逻辑:
private void getData() { String json_req = "json_req"; String url = getContext().getString(R.string.CURRENT_STATUS); JsonObjectRequest req = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { try { JSONObject object = new JSONObject(response.toString()); JSONArray data = object.getJSONArray("results"); current.clear(); // 先清空旧数据,避免重复添加 for (int i = 0; i < data.length(); i++) { JSONObject json = data.getJSONObject(i); final CurrentEntry c = new CurrentEntry(); // 先设置已知字段 c.setPeople(json.getString("my_people")); String temp = json.getString("my_timetime"); temp = temp.substring(11); temp = temp.substring(0, temp.length() - 4); c.setEstimate(temp); String userUrl = json.getString("name"); JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, userUrl, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { try { String foodie_name = response.getString("username"); c.setName(foodie_name); // 修正变量名错误 adapt.notifyDataSetChanged(); // 单个条目更新后通知adapter } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { error.printStackTrace(); // 打印错误方便调试 } }) { @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String, String> headers = new HashMap<>(); String credentials = "your_username:your_password"; // 替换为实际凭证 String auth = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); headers.put("Content-type", "application/json"); headers.put("Authorization", auth); return headers; } }; AppController.getInstance().addToRequestQueue(request, "second_req_" + i); // 给每个请求唯一tag current.add(c); } // 初始化adapter adapt = new NewAdapter(current, getActivity()); recyclerView.setAdapter(adapt); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { error.printStackTrace(); } }) { @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String, String> headers = new HashMap<>(); String credentials = "your_username:your_password"; // 替换为实际凭证 String auth = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); headers.put("Content-type", "application/json"); headers.put("Authorization", auth); return headers; } }; AppController.getInstance().addToRequestQueue(req, json_req); }
额外优化:给Adapter添加内部过滤方法
让NewAdapter支持直接更新过滤后的列表,避免重复创建adapter:
public class NewAdapter extends RecyclerView.Adapter<NewAdapter.ViewHolder> { private List<CurrentEntry> mList; private Context mContext; public NewAdapter(List<CurrentEntry> list, Context context) { this.mList = list; this.mContext = context; } // 添加过滤更新方法 public void setFilteredList(List<CurrentEntry> filteredList) { this.mList = filteredList; notifyDataSetChanged(); } // 其他ViewHolder、onCreateViewHolder、onBindViewHolder等方法... }
初始化时设置LayoutManager
在Fragment的onViewCreated里提前设置一次即可:
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); recyclerView = view.findViewById(R.id.your_recycler_view_id); // 只设置一次LayoutManager recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); current = new ArrayList<>(); getData(); addTextListener(); }
内容的提问来源于stack exchange,提问作者Satyam Gondhale
相关产品推荐
相关产品推荐

