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

Android Studio实现SearchView传参调用API并展示RecyclerView求助

问题分析与修复方案

现有代码的核心问题

  • API请求URL错误:USDA搜索API的查询参数是query,你的URL写成了?=,应该改为?query=,否则API无法识别搜索关键词。
  • JSON键名错误:response.getJSONArray(" foods")中键名带了开头空格,正确的键是"foods",这会直接导致JSON解析异常。
  • 无请求防抖:用户每输入一个字符就发起请求,会产生大量无效请求,既浪费资源也可能触发API频率限制。
  • 数据源未重置:每次新搜索前未清空foodModelList,旧数据会和新数据叠加显示。
  • Toast未触发显示:Toast.makeText()后缺少.show()方法,错误提示不会弹出。
  • 变量名拼写错误:proteingrmas.toString()应为proteingrams.toString(),会导致编译或运行错误。
  • RecyclerView未更新:添加数据后未通知适配器刷新,列表不会显示新数据。
  • JSON解析逻辑错误:USDA API的value字段嵌套在foodNutrients数组中,直接获取value会抛出异常,需要正确解析嵌套结构。

修复后的完整代码

1. 防抖工具与请求逻辑

先在Activity中声明防抖用的Handler和Runnable:

private Handler searchHandler = new Handler();
private Runnable searchRunnable;

然后修改onQueryTextChange方法:

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

    @Override
    public boolean onQueryTextChange(String newText) {
        // 移除之前的延迟请求,实现防抖
        if (searchRunnable != null) {
            searchHandler.removeCallbacks(searchRunnable);
        }

        // 输入为空时清空列表
        if (TextUtils.isEmpty(newText)) {
            foodModelList.clear();
            recyclerViewAdapter.notifyDataSetChanged();
            return true;
        }

        // 延迟500ms发起请求,用户停止输入后才执行
        searchRunnable = () -> {
            // 修正URL参数
            String url = "https://fdc.nal.usda.gov/fdc/v1/foods/search?query=" + newText + "&dataType=Foundation,SR%20Legacy&api_key=my_apikey";

            JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null,
                    response -> {
                        try {
                            // 清空旧数据
                            foodModelList.clear();
                            JSONArray jsonArray = response.getJSONArray("foods");
                            for (int i = 0; i < jsonArray.length(); i++) {
                                JSONObject foodObj = jsonArray.getJSONObject(i);
                                String foodName = foodObj.getString("description");

                                // 解析蛋白质含量(嵌套在foodNutrients数组中)
                                String proteinGrams = "0";
                                JSONArray nutrientsArray = foodObj.getJSONArray("foodNutrients");
                                for (int j = 0; j < nutrientsArray.length(); j++) {
                                    JSONObject nutrientObj = nutrientsArray.getJSONObject(j);
                                    if (nutrientObj.getString("nutrientName").equals("Protein")) {
                                        proteinGrams = nutrientObj.getString("value");
                                        break;
                                    }
                                }

                                setData(foodName, proteinGrams);
                            }
                            // 通知适配器更新
                            recyclerViewAdapter.notifyDataSetChanged();
                        } catch (JSONException e) {
                            e.printStackTrace();
                            Toast.makeText(SearchFoods.this, "数据解析失败", Toast.LENGTH_SHORT).show();
                        }
                    },
                    error -> {
                        String errorMsg = error.getMessage() != null ? error.getMessage() : "请求失败";
                        Toast.makeText(SearchFoods.this, errorMsg, Toast.LENGTH_SHORT).show();
                    });

            requestQueue.add(jsonObjectRequest);
        };

        searchHandler.postDelayed(searchRunnable, 500);
        return true;
    }
});

2. 修复setData方法

public void setData(String foodname, String proteingrams) {
    // 修正变量名拼写错误,避免空指针
    String safeFoodName = foodname != null ? foodname : "未知食物";
    String safeProtein = proteingrams != null ? proteingrams : "0";
    foodModelList.add(new FoodModel(safeFoodName, "70", "14", safeProtein, "47.6", "11.9", "2.7", "1"));
}

额外优化建议

  • API密钥安全:不要把API密钥硬编码在代码中,建议放在local.properties文件中,通过BuildConfig读取。
  • 使用Gson简化解析:可以用Gson将JSON直接映射到实体类,避免手动解析JSON的繁琐和错误,比如创建FoodResponse、Food、FoodNutrient等实体类。
  • 分页加载:如果API支持分页,可以添加分页逻辑,避免一次性加载过多数据导致列表卡顿。
  • 网络状态判断:发起请求前检查网络连接,给用户友好提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:36:10