Android中如何用Retrofit解析嵌套JSON并在两个RecyclerView展示?
在Android中用Retrofit解析嵌套JSON并展示到RecyclerView的完整方案
我来帮你一步步解决这个问题,从解析嵌套JSON到把数据展示在两个RecyclerView上,全程清晰明了:
1. 先理清你的JSON结构
首先把你提供的JSON格式化一下,方便理解层级:
{ "204": { "input": [ { "name": "nima", "school": "alavi", "age": 20, "scheduled": false } ], "output": [ { "name": "amin", "school": "alavi", "age": 24, "scheduled": false } ], "internal": [], "external": [] } }
结构说明:
- 最外层是一个对象,键为
"204",对应的值是一个包含4个数组的对象 input和output数组里的元素是相同结构的用户对象,包含name、school、age、scheduled四个字段
2. 创建对应的数据模型类(POJO)
Retrofit默认用Gson解析JSON,我们需要创建和JSON结构一一对应的Java类,用@SerializedName注解映射JSON键和Java字段(尤其是像"204"这种数字开头的键,Java字段不能直接用数字命名)。
① 最内层的User类(对应input/output里的用户对象)
public class User { @SerializedName("name") private String name; @SerializedName("school") private String school; @SerializedName("age") private int age; @SerializedName("scheduled") private boolean scheduled; // Getter方法(Setter可选,根据需求添加) public String getName() { return name; } public String getSchool() { return school; } public int getAge() { return age; } public boolean isScheduled() { return scheduled; } }
② 中间层的ResponseData类(对应"204"的值)
public class ResponseData { @SerializedName("input") private List<User> inputUsers; @SerializedName("output") private List<User> outputUsers; @SerializedName("internal") private List<User> internalUsers; @SerializedName("external") private List<User> externalUsers; // Getter方法 public List<User> getInputUsers() { return inputUsers; } public List<User> getOutputUsers() { return outputUsers; } }
③ 最外层的ApiResponse类(对应整个JSON)
public class ApiResponse { @SerializedName("204") private ResponseData responseData; public ResponseData getResponseData() { return responseData; } }
3. 配置Retrofit环境
首先在Module级别的build.gradle文件中添加依赖:
// Retrofit核心库 implementation 'com.squareup.retrofit2:retrofit:2.9.0' // Gson转换器(用于解析JSON) implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // RecyclerView库 implementation 'androidx.recyclerview:recyclerview:1.3.2'
然后创建Retrofit接口ApiService,定义你的网络请求:
public interface ApiService { @GET("your-api-endpoint") // 替换成你的实际接口路径 Call<ApiResponse> fetchUserData(); }
接着初始化Retrofit实例:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("your-base-url/") // 替换成你的接口基础URL,比如https://example.com/api/ .addConverterFactory(GsonConverterFactory.create()) .build(); ApiService apiService = retrofit.create(ApiService.class);
4. 发起请求并绑定数据到RecyclerView
调用接口方法发起异步请求,拿到数据后分别给两个RecyclerView设置适配器:
apiService.fetchUserData().enqueue(new Callback<ApiResponse>() { @Override public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) { if (response.isSuccessful() && response.body() != null) { // 解析出input和output列表 ResponseData data = response.body().getResponseData(); List<User> inputUserList = data.getInputUsers(); List<User> outputUserList = data.getOutputUsers(); // 初始化适配器并绑定到RecyclerView UserAdapter inputAdapter = new UserAdapter(inputUserList); UserAdapter outputAdapter = new UserAdapter(outputUserList); RecyclerView inputRv = findViewById(R.id.rv_input); RecyclerView outputRv = findViewById(R.id.rv_output); // 设置布局管理器(这里用线性布局,你也可以换成网格/瀑布流) inputRv.setLayoutManager(new LinearLayoutManager(MainActivity.this)); inputRv.setAdapter(inputAdapter); outputRv.setLayoutManager(new LinearLayoutManager(MainActivity.this)); outputRv.setAdapter(outputAdapter); } } @Override public void onFailure(Call<ApiResponse> call, Throwable t) { // 处理请求失败的情况,比如弹出提示 Toast.makeText(MainActivity.this, "请求失败:" + t.getMessage(), Toast.LENGTH_SHORT).show(); } });
5. 编写RecyclerView的适配器和布局
① 创建用户列表项布局item_user.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="18sp" android:textStyle="bold"/> <TextView android:id="@+id/tv_school" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="14sp" android:layout_marginTop="4dp"/> <TextView android:id="@+id/tv_age" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="14sp" android:layout_marginTop="4dp"/> <TextView android:id="@+id/tv_scheduled" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="14sp" android:layout_marginTop="4dp"/> </LinearLayout>
② 编写UserAdapter类
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserViewHolder> { private List<User> userList; public UserAdapter(List<User> userList) { this.userList = userList; } @NonNull @Override public UserViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_user, parent, false); return new UserViewHolder(itemView); } @Override public void onBindViewHolder(@NonNull UserViewHolder holder, int position) { User user = userList.get(position); holder.tvName.setText(user.getName()); holder.tvSchool.setText(user.getSchool()); holder.tvAge.setText(String.valueOf(user.getAge())); holder.tvScheduled.setText(user.isScheduled() ? "已安排" : "未安排"); } @Override public int getItemCount() { return userList.size(); } // ViewHolder类 public static class UserViewHolder extends RecyclerView.ViewHolder { TextView tvName, tvSchool, tvAge, tvScheduled; public UserViewHolder(@NonNull View itemView) { super(itemView); tvName = itemView.findViewById(R.id.tv_name); tvSchool = itemView.findViewById(R.id.tv_school); tvAge = itemView.findViewById(R.id.tv_age); tvScheduled = itemView.findViewById(R.id.tv_scheduled); } } }
最后别忘了加权限
在AndroidManifest.xml中添加网络权限:
<uses-permission android:name="android.permission.INTERNET"/>
内容的提问来源于stack exchange,提问作者Amin Najafi
相关产品推荐
相关产品推荐

