Retrofit onResponse未执行仅onFailure触发,图表数据请求失败求助
Retrofit请求进入onFailure的问题排查与修复
核心问题分析
JSON结构与接口返回类型不匹配
接口返回的是JSON数组([]包裹),但你定义的init()方法返回Call<ChartResponse>,单个对象无法匹配数组结构,直接导致解析失败进入onFailure。实体类字段错误
- 字段使用
static修饰:Gson基于实例对象赋值,static字段属于类,无法被Gson正确注入值,会导致字段始终为null。 - 字段类型不匹配:JSON中
current/temp/hum的元素是字符串(如"10.79"),但实体类定义为List<Float>,解析时会抛出类型转换异常。
- 字段使用
依赖版本冲突
OkHttp(3.2.0)与Logging-Interceptor(3.6.0)版本不一致,可能导致请求过程中出现未知异常。代码逻辑错误
即使请求成功,调用ChartResponse.getHum()静态方法获取数据,既不符合实体类设计,也无法正确提取数组中的数据。
分步修复方案
1. 修正Api接口定义
将返回类型改为数组对应的Call<List<DataItem>>,匹配JSON数组结构:
public interface Api { @FormUrlEncoded @POST("register.php") Call<RegisterResponse> register( @Field("voltage") String voltage, @Field("current") String current, @Field("temp") String temp ); @GET("fetch.php") Call<List<DataItem>> init(); // 修改为List包裹的DataItem }
2. 重新定义实体类DataItem
去掉static修饰符,统一字段类型为List<String>(后续再转换为数值):
public class DataItem { @SerializedName("voltage") @Expose private List<String> voltage; @SerializedName("current") @Expose private List<String> current; @SerializedName("temp") @Expose private List<String> temp; @SerializedName("hum") @Expose private List<String> hum; // Getter和Setter方法(非静态) public List<String> getVoltage() { return voltage; } public void setVoltage(List<String> voltage) { this.voltage = voltage; } public List<String> getCurrent() { return current; } public void setCurrent(List<String> current) { this.current = current; } public List<String> getTemp() { return temp; } public void setTemp(List<String> temp) { this.temp = temp; } public List<String> getHum() { return hum; } public void setHum(List<String> hum) { this.hum = hum; } }
3. 修正getData方法逻辑
适配新的接口返回类型,正确提取数据并处理图表渲染:
private void getData() { Call<List<DataItem>> call = api.init(); call.enqueue(new Callback<List<DataItem>>() { @Override public void onResponse(Call<List<DataItem>> call, Response<List<DataItem>> response) { Log.e("CHART_RESPONSE", "请求成功"); if (response.isSuccessful() && response.body() != null) { List<DataItem> dataItems = response.body(); // 从数组中提取湿度数据(对应JSON的第4个元素) List<String> humList = dataItems.get(3).getHum(); BarChart barchart = findViewById(R.id.fragment_verticalbarchart_chart); ArrayList<BarEntry> completed = new ArrayList<>(); // 将字符串转换为Float并构建图表数据 for (int i = 0; i < humList.size(); i++) { float humValue = Float.parseFloat(humList.get(i)); BarEntry entry = new BarEntry(i, humValue); completed.add(entry); } BarDataSet barDataSet = new BarDataSet(completed, "湿度"); barDataSet.setColor(Color.rgb(0, 155, 0)); BarData data = new BarData(barDataSet); barchart.setData(data); barchart.invalidate(); } } @Override public void onFailure(Call<List<DataItem>> call, Throwable t) { // 打印详细错误信息,方便排查 Log.e("CHART_RESPONSE", "请求失败:" + t.getMessage()); t.printStackTrace(); } }); }
4. 统一依赖版本
修改build.gradle中的依赖,确保OkHttp系列版本一致:
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' implementation 'com.google.code.gson:gson:2.6.2' implementation 'com.squareup.retrofit2:retrofit:2.0.2' implementation 'com.squareup.retrofit2:converter-gson:2.0.2' // 统一OkHttp版本 implementation 'com.squareup.okhttp3:okhttp:3.12.0' implementation 'com.squareup.okhttp3:logging-interceptor:3.12.0'
额外排查建议
- 查看Logcat中的错误堆栈信息:
onFailure中打印t.printStackTrace()可以看到具体失败原因(如网络连接失败、JSON解析异常等)。 - 确认设备与服务器处于同一局域网:
192.8.1.103是局域网IP,需确保手机/模拟器和服务器在同一网络下。 - 用浏览器或Postman测试
http://192.8.1.103/PHP-API/fetch.php,确认接口返回的JSON格式正确且能正常访问。
内容的提问来源于stack exchange,提问作者鳳凰院凶真
相关产品推荐
相关产品推荐

