Android开发:如何通过API获取数据填充至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

