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

Android Fragment Toolbar中SearchView搜索无效果问题排查与实现

排查SearchView无结果显示的问题及正确实现方案

我看了你的代码,能发现几个导致搜索无结果的关键问题,咱们一步步来解决:


核心问题分析

  • 错误1:过滤后传递了原列表而非过滤结果
    在onQueryTextChange方法里,你明明已经遍历生成了过滤后的filteredList,但最后却调用adapter.setFilter(itemrestaurants),相当于把原始未过滤的列表重新传给适配器,自然看不到任何搜索结果。

  • 错误2:大小写匹配逻辑不一致+冗余操作
    你已经把搜索关键词newText转成了小写,但判断餐厅名称时又多做了一次newText.toLowerCase()的冗余操作;更关键的是,餐厅地址row.getRestaurant_address()没转小写,会导致用户搜索"main"时,匹配不到"Main Street"这类大小写不一致的地址。

  • 错误3:缺少原始数据备份,多次过滤会丢失数据
    你现在直接基于itemrestaurants做过滤,但如果第一次过滤后,这个列表的内容被替换成过滤后的子集,后续的过滤就会基于这个缩小的列表,而不是全部原始餐厅数据,最终导致搜索结果越来越少甚至无结果。


修正后的关键代码实现

1. 调整成员变量,添加原始数据备份

public class Restaurant extends Fragment{ 
    RecyclerView restaurant_recycler; 
    RestaurantsAdapter adapter; 
    private ProgressDialog sweetProgressDialog; 
    SessionManager sessionManager; 
    List<Restaurant_model> itemrestaurants; 
    // 新增:保存所有原始餐厅数据的列表
    private List<Restaurant_model> originalRestaurants;
    private Context mContext; 

    // ... 其他代码
}

2. 初始化原始列表,并在网络请求后同步数据

在onCreateView里初始化原始列表:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    View v = inflater.inflate(R.layout.activity_restaurant, container, false); 
    restaurant_recycler = (RecyclerView) v.findViewById(R.id.recycler_view_restaurant); 
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false); 
    itemrestaurants = new ArrayList<>();
    // 初始化原始数据列表
    originalRestaurants = new ArrayList<>();
    adapter = new RestaurantsAdapter(getContext(), itemrestaurants); 
    restaurant_recycler.setLayoutManager(mLayoutManager); 
    restaurant_recycler.setItemAnimator(new DefaultItemAnimator()); 
    restaurant_recycler.setAdapter(adapter); 
    sweetProgressDialog = new ProgressDialog(getContext(), R.style.MyAlertDialogStyle); 
    sessionManager = new SessionManager(getContext()); 
    show_restaurants(); 
    return v; 
}

在show_restaurants的网络请求成功回调里,同步原始数据:

try {
    Log.e("tag", "response " + response);
    JSONArray array = new JSONArray(response);
    // 清空列表,避免重复添加数据
    itemrestaurants.clear();
    originalRestaurants.clear();
    for (int i = 0; i < array.length(); i++) {
        JSONObject thisOBj = (JSONObject) array.get(i);
        Restaurant_model restaurant = new Restaurant_model(
            thisOBj.getString("id"),
            thisOBj.getString("name"),
            thisOBj.getString("address"),
            thisOBj.getString("image")
        );
        itemrestaurants.add(restaurant);
        originalRestaurants.add(restaurant);
    }
    adapter.notifyDataSetChanged();
} catch (JSONException e) {
    // 保留你的异常处理代码
    if (sweetProgressDialog.isShowing()) {
        sweetProgressDialog.dismiss();
    }
    Log.i("myTag", e.toString());
    Toast.makeText(getContext(), "Parsing error", Toast.LENGTH_SHORT).show();
}

3. 修正onQueryTextChange方法

@Override
public boolean onQueryTextChange(String newText) {
    newText = newText.toLowerCase().trim(); // 去掉首尾空格,优化搜索体验
    List<Restaurant_model> filteredList = new ArrayList<>();
    // 基于原始数据列表做过滤,保证每次搜索都是完整数据集
    for (Restaurant_model row : originalRestaurants) {
        String restaurantName = row.getRestaurant_name().toLowerCase();
        String restaurantAddress = row.getRestaurant_address().toLowerCase();
        // 名称或地址包含关键词就加入过滤列表
        if (restaurantName.contains(newText) || restaurantAddress.contains(newText)) {
            filteredList.add(row);
        }
    }
    // 传递过滤后的列表给适配器
    adapter.setFilter(filteredList);
    return true;
}

4. 确保适配器的setFilter方法正确实现

你的RestaurantsAdapter里必须有正确的setFilter方法,用来更新数据源并通知RecyclerView刷新:

public class RestaurantsAdapter extends RecyclerView.Adapter<RestaurantsAdapter.ViewHolder> {
    private List<Restaurant_model> mRestaurantList;
    private Context mContext;

    // 构造方法
    public RestaurantsAdapter(Context context, List<Restaurant_model> restaurantList) {
        mContext = context;
        mRestaurantList = restaurantList;
    }

    // 过滤方法
    public void setFilter(List<Restaurant_model> filteredList) {
        mRestaurantList = filteredList;
        notifyDataSetChanged(); // 必须调用此方法通知RecyclerView更新UI
    }

    // ... 其他ViewHolder、onCreateViewHolder、onBindViewHolder等方法
}

5. 优化onQueryTextSubmit方法

@Override
public boolean onQueryTextSubmit(String query) {
    // 提交搜索后隐藏软键盘,提升体验
    View view = getActivity().getCurrentFocus();
    if (view != null) {
        InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }
    return true;
}

总结

修改完成后,你的SearchView应该就能正常显示过滤结果了。核心要点是:

  • 始终基于原始完整数据做过滤,避免多次过滤后数据丢失
  • 确保过滤后的列表正确传递给适配器
  • 适配器必须调用notifyDataSetChanged()通知RecyclerView刷新UI

内容的提问来源于stack exchange,提问作者Ehtisham habib

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:54:37