Retrofit处理搜索无效数据:天气APP无效城市输入崩溃解决
嘿,这个问题我熟!之前帮朋友调试天气APP的时候也碰到过一模一样的情况——用户乱输一串字符就崩溃,核心原因就是咱们没处理API返回的错误状态,也没做前置的输入校验。咱们分几步搞定:
解决步骤
1. 先给用户输入加一层前置校验
在调用API之前,先把明显无效的输入拦下来,比如空字符串、纯空格、带特殊字符的乱码。这样既能减少无效的API请求,也能提前给用户提示。
示例代码(假设你用EditText接收输入):
// 获取用户输入并去除首尾空格 String inputCity = cityEditText.getText().toString().trim(); // 校验1:不能是空输入 if (inputCity.isEmpty()) { Toast.makeText(this, "请输入有效的城市名称", Toast.LENGTH_SHORT).show(); return; } // 校验2:简单过滤特殊字符(可选,比如只允许中英文、空格和少数合法符号) if (!inputCity.matches("[a-zA-Z\\u4e00-\\u9fa5\\s]+")) { Toast.makeText(this, "请输入有效的城市名称", Toast.LENGTH_SHORT).show(); return; } // 校验通过,再调用API getWeatherDataByCity(inputCity);
2. 处理API响应的错误状态
OpenWeatherMap API查询无效城市时,会返回404状态码,同时响应体里会提示"city not found"。咱们必须在网络请求的回调里判断响应是否成功,不能直接解析数据。
如果你用OkHttp,修改请求逻辑如下:
private void getWeatherDataByCity(String city) { HashMap<String, String> params = new HashMap<>(); params.put("q", city); params.put("appid", "你的API_KEY"); params.put("units", "metric"); // 按需设置单位,比如摄氏度 OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("https://api.openweathermap.org/data/2.5/weather") .get() .params(new FormBody.Builder().addAll(params).build()) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { // 网络请求失败(比如无网)的情况 runOnUiThread(() -> { Toast.makeText(MainActivity.this, "网络连接失败,请稍后重试", Toast.LENGTH_SHORT).show(); }); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { runOnUiThread(() -> { // 先判断响应是否成功(状态码200-299) if (!response.isSuccessful()) { // 状态码不对,比如404就是城市不存在 Toast.makeText(MainActivity.this, "请输入有效的城市名称", Toast.LENGTH_SHORT).show(); return; } // 正常解析数据的逻辑,一定要加try-catch防止解析崩溃 try { String responseBody = response.body().string(); // 这里写你的JSON解析代码,比如解析城市名、温度等 JSONObject jsonObj = new JSONObject(responseBody); String cityName = jsonObj.getString("name"); // ...其他字段解析 } catch (Exception e) { // 解析出错(比如API返回格式变动) Toast.makeText(MainActivity.this, "数据解析失败,请稍后重试", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } }); } }); }
如果用Retrofit,处理方式类似:
// 假设你已经定义了WeatherResponse实体类和WeatherApi接口 Call<WeatherResponse> call = weatherApi.getWeatherByCity(city, "你的API_KEY"); call.enqueue(new Callback<WeatherResponse>() { @Override public void onResponse(Call<WeatherResponse> call, Response<WeatherResponse> response) { if (!response.isSuccessful()) { // 响应失败,提示用户 Toast.makeText(MainActivity.this, "请输入有效的城市名称", Toast.LENGTH_SHORT).show(); return; } // 正常处理返回数据 WeatherResponse weatherData = response.body(); if (weatherData != null) { // 更新UI显示天气信息 } } @Override public void onFailure(Call<WeatherResponse> call, Throwable t) { // 网络失败提示 Toast.makeText(MainActivity.this, "网络连接失败", Toast.LENGTH_SHORT).show(); } });
3. 关键提醒:给解析逻辑加try-catch
就算API返回成功,也可能因为JSON格式变动、字段缺失等原因导致解析崩溃,所以一定要把解析代码放在try-catch块里,捕获异常并提示用户。
这样一套操作下来,不管用户是乱输字符、网络不好还是API返回错误,APP都不会崩溃,而是友好地给用户提示~
内容的提问来源于stack exchange,提问作者chand mohd
相关产品推荐
相关产品推荐

