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

Retrofit解析无URL响应求助:JSON数组解析及TextView赋值问题

解决Retrofit无法获取JSON数组响应的问题

我完全懂你现在的困扰——明明搭好了Retrofit的整套结构,却拿不到半点响应,这种情况我也碰到过好几次!咱们从最容易踩坑的地方开始排查,一步步解决:

1. 先检查Retrofit客户端的核心配置

这是最容易出错的基础环节:

  • 必须添加JSON解析转换器:Retrofit本身不会自动解析JSON,一定要加上GsonConverterFactory(如果用Gson的话),不然接口返回的响应根本没法转成你的DistrictDTO对象。正确配置示例:
    public class RetrofitClient {
        private static final String BASE_URL = "https://your-api-base-url.com/"; // 注意末尾的/必须加
        private static Retrofit retrofit;
    
        public static Retrofit getClient() {
            if (retrofit == null) {
                retrofit = new Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        .addConverterFactory(GsonConverterFactory.create()) // 关键!不能少
                        .build();
            }
            return retrofit;
        }
    }
    
  • BaseUrl必须以/结尾:如果你的baseUrl是https://xxx.com/api,而接口路径是districts,Retrofit会拼接成https://xxx.comdistricts,直接导致请求地址错误,这坑我踩过不止一次!

2. 确认Api Service的接口定义是否正确

因为你要解析的是对象数组,接口的返回类型必须对应:

  • 接口方法的返回值应该是Call<List<DistrictDTO>>,而不是单个的Call<DistrictDTO>!示例:
    public interface ApiService {
        @GET("districts") // 这里的路径要和后端接口完全匹配
        Call<List<DistrictDTO>> getDistricts();
    }
    
  • 核对HTTP方法(@GET/@POST等)和路径是否和后端一致,比如后端是POST接口,你用@GET肯定拿不到数据。

3. 检查DistrictDTO类的映射正确性

Gson解析的核心是字段匹配,这里最容易出细节问题:

  • 字段名必须和JSON键一致,或者用@SerializedName映射:比如JSON里的键是district_id,你的DTO字段是districtId,那必须加注解:
    public class DistrictDTO {
        @SerializedName("district_id")
        private int districtId;
        @SerializedName("district_name")
        private String districtName;
    
        // 必须要有无参构造函数!Gson需要它来实例化对象
        public DistrictDTO() {}
    
        // Getter和Setter方法
        public int getDistrictId() { return districtId; }
        public void setDistrictId(int districtId) { this.districtId = districtId; }
        public String getDistrictName() { return districtName; }
        public void setDistrictName(String districtName) { this.districtName = districtName; }
    }
    
  • 确保字段类型和JSON里的类型完全匹配:比如JSON里是数字类型的ID,DTO里不能用String,否则解析会失败。
  • 一定要保留无参构造函数,不然Gson没法创建对象。

4. Activity中的调用逻辑排查

异步请求和UI更新的细节很容易忽略:

  • 必须处理onFailure回调:很多时候问题出在这里,比如网络超时、域名解析失败,一定要打印错误信息:
    ApiService apiService = RetrofitClient.getClient().create(ApiService.class);
    Call<List<DistrictDTO>> call = apiService.getDistricts();
    call.enqueue(new Callback<List<DistrictDTO>>() {
        @Override
        public void onResponse(Call<List<DistrictDTO>> call, Response<List<DistrictDTO>> response) {
            if (response.isSuccessful() && response.body() != null) {
                // 这里处理成功的响应,注意更新UI要在主线程
                runOnUiThread(() -> {
                    // 把数据设置到TextView,比如拼接所有 districtName
                    StringBuilder sb = new StringBuilder();
                    for (DistrictDTO district : response.body()) {
                        sb.append(district.getDistrictName()).append("\n");
                    }
                    yourTextView.setText(sb.toString());
                });
            } else {
                // 响应成功但没有数据,打印响应码看看
                Log.e("Retrofit", "Response failed: " + response.code());
            }
        }
    
        @Override
        public void onFailure(Call<List<DistrictDTO>> call, Throwable t) {
            // 这里打印错误信息,能直接定位问题!
            Log.e("RetrofitError", "Request failed: " + t.getMessage(), t);
        }
    });
    
  • 更新UI必须在主线程:Retrofit的onResponse和onFailure是在子线程执行的,直接更新TextView会崩溃,一定要用runOnUiThread或者借助ViewModel/LiveData。
  • 别忘了加网络权限:在AndroidManifest.xml里添加<uses-permission android:name="android.permission.INTERNET" />,没有这个权限的话,连网络请求都发不出去!

5. 调试小技巧:先看原始响应

如果还是找不到问题,先跳过解析,直接获取原始的响应字符串,确认是不是真的拿到了JSON:

// 临时修改ApiService的方法
@GET("districts")
Call<ResponseBody> getRawDistricts();

// 调用时打印原始内容
Call<ResponseBody> rawCall = apiService.getRawDistricts();
rawCall.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        if (response.isSuccessful()) {
            try {
                String rawJson = response.body().string();
                Log.d("RawJSON", rawJson); // 看看返回的是不是预期的数组结构
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        Log.e("RawError", t.getMessage(), t);
    }
});

这样能快速确认是网络请求的问题,还是JSON解析的问题。

按照上面的步骤一步步排查,大概率能找到问题所在!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:09:25