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

Android开发:如何通过API获取数据填充至Spinner?

问题:Retrofit获取区县列表并加载到Spinner失败

场景说明

需要将API返回的区县列表展示在Spinner中,API响应示例如下:

{
    "districts": [
        { "district": "ANANTNAG" },
        { "district": "BADGAM" },
        { "district": "BANDIPORA" },
        { "district": "BARAMULLA" },
        { "district": "DODA" },
        { "district": "GANDERBAL" },
        { "district": "JAMMU" },
        { "district": "KARGIL" },
        { "district": "KATHUA" },
        { "district": "KISHTWAR" },
        { "district": "KULGAM" },
        { "district": "KUPWARA" },
        { "district": "LEH LADAKH" },
        { "district": "POONCH" },
        { "district": "PULWAMA" },
        { "district": "RAJAURI" },
        { "district": "RAMBAN" },
        { "district": "REASI" },
        { "district": "SAMBA" },
        { "district": "SHOPIAN" },
        { "district": "SRINAGAR" },
        { "district": "UDHAMPUR" },
        { "district": "JAMMU AND KASHMIR" }
    ],
    "Request_type": "districts",
    "responseCode": "Success"
}

已创建对应POJO类,但实现Retrofit调用后无法正常工作,当前getdistricts方法代码:

private void getdistricts(String state) {

    JSONObject mJobj = new JSONObject();

    try {
        mJobj.put("state", state);
        mJobj.put(REQUEST, "districts");
    } catch (JSONException e) {
        e.printStackTrace();
    }


    Call<districtresponse> call = RetrofitClient.getInstance().getApi().getDistrict(mJobj);
    call.enqueue(new Callback<districtresponse>() {
        @Override
        public void onResponse(Call<districtresponse> call, Response<districtresponse> response) {

            String status = response.body().getResponseCode();

            if (status.equalsIgnoreCase("Success")){
                district_list = response.body().getDistricts();

                districts = new ArrayAdapter<String>(this,R.layout.dist_list,district_list);
            }

        }
        @Override
        public void onFailure(Call<districtresponse> call, Throwable t) {


        }
    });

}

问题分析与修复步骤

1. 上下文错误(ArrayAdapter初始化)

代码中new ArrayAdapter<String>(this,R.layout.dist_list,district_list)里的this是匿名Callback类的上下文,不是Activity/Fragment的上下文,会导致Adapter初始化失败。需替换为Activity实例(如YourActivityName.this)或Fragment的getContext()。

2. 数据源类型不匹配

district_list是POJO对象列表(List<District>),而ArrayAdapter<String>需要字符串列表。需遍历POJO列表,提取每个区县的名称转为字符串集合。

3. 未给Spinner设置Adapter

创建完Adapter后,没有调用yourSpinner.setAdapter(adapter)将Adapter绑定到Spinner,导致数据无法显示。

4. 空指针风险

直接调用response.body().getResponseCode()前,未判断response.isSuccessful()和response.body() != null,若API响应失败或body为空会抛出空指针异常。

5. 请求体处理不规范

手动构建JSONObject作为请求体,容易出错且不符合Retrofit最佳实践,建议用POJO类封装请求参数。


修正后的完整代码

步骤1:创建请求体POJO类

public class DistrictRequest {
    private String state;
    private String Request_type;

    public DistrictRequest(String state, String requestType) {
        this.state = state;
        this.Request_type = requestType;
    }
}

步骤2:修正Retrofit接口定义

public interface ApiService {
    @POST("your-api-endpoint") // 替换为实际API接口地址
    Call<districtresponse> getDistrict(@Body DistrictRequest request);
}

步骤3:修改getdistricts方法

private void getdistricts(String state) {
    DistrictRequest request = new DistrictRequest(state, "districts");

    Call<districtresponse> call = RetrofitClient.getInstance().getApi().getDistrict(request);
    call.enqueue(new Callback<districtresponse>() {
        @Override
        public void onResponse(Call<districtresponse> call, Response<districtresponse> response) {
            // 先校验响应有效性
            if (response.isSuccessful() && response.body() != null) {
                String status = response.body().getResponseCode();
                if ("Success".equalsIgnoreCase(status)) {
                    // 提取区县名称为字符串列表
                    List<String> districtNames = new ArrayList<>();
                    for (District district : response.body().getDistricts()) {
                        districtNames.add(district.getDistrict());
                    }

                    // 使用Activity上下文初始化Adapter
                    ArrayAdapter<String> adapter = new ArrayAdapter<>(YourActivity.this, R.layout.dist_list, districtNames);
                    // 将Adapter绑定到Spinner
                    yourSpinner.setAdapter(adapter);
                }
            }
        }

        @Override
        public void onFailure(Call<districtresponse> call, Throwable t) {
            // 添加错误日志,方便排查
            Log.e("DistrictLoadError", "加载区县失败: " + t.getMessage());
        }
    });
}

步骤4:检查POJO类的序列化配置

确保POJO类字段与JSON响应完全匹配,可通过@SerializedName注解处理大小写或字段名差异:

public class District {
    @SerializedName("district")
    private String district;

    public String getDistrict() {
        return district;
    }
}

public class districtresponse {
    @SerializedName("districts")
    private List<District> districts;
    @SerializedName("responseCode")
    private String responseCode;

    public List<District> getDistricts() {
        return districts;
    }

    public String getResponseCode() {
        return responseCode;
    }
}

步骤5:确认Retrofit初始化配置

确保RetrofitClient添加了Gson转换器:

public class RetrofitClient {
    private static Retrofit retrofit;
    private static final String BASE_URL = "你的API基础地址";

    public static Retrofit getInstance() {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }

    public ApiService getApi() {
        return retrofit.create(ApiService.class);
    }
}

额外检查项

  • 确认AndroidManifest.xml添加了网络权限:<uses-permission android:name="android.permission.INTERNET" />
  • 若API为HTTPS,检查证书配置是否正确,避免SSL握手失败
  • 验证API请求参数是否符合后端要求(如state参数的格式、取值范围)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 10:50:26