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

Retrofit2解析API返回JSON数组并适配Expandable List View问题

Retrofit2解析JSON后转可检索结构适配ExpandableListView方案

1. 确认数据模型类

先确保你的数据模型和API返回结构完全对应:

// 对应SUCCESS数组内的用户对象
public class User {
    @SerializedName("user_id")
    private String userId; // 若user_id是数字类型,改为int即可
    @SerializedName("email")
    private String email;

    // Getter & Setter
    public String getUserId() { return userId; }
    public void setUserId(String userId) { this.userId = userId; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

// API返回的根模型
public class ApiResponse {
    @SerializedName("SUCCESS")
    private List<User> successList;

    public List<User> getSuccessList() { return successList; }
    public void setSuccessList(List<User> successList) { this.successList = successList; }
}

2. 转成可通过user_id快速检索的结构

如果要高效通过user_id查找用户,用Map比数组更合适(数组检索需遍历,Map可实现O(1)查询)。若一定要用数组,也可以基于List转换:

// 假设已通过Retrofit回调拿到ApiResponse实例
ApiResponse response = ...;
List<User> userList = response.getSuccessList();

// 转为Map:key=user_id,value=User对象
Map<String, User> userMap = new HashMap<>();
for (User user : userList) {
    userMap.put(user.getUserId(), user);
}

// 若需转为数组
User[] userArray = userList.toArray(new User[0]);
// 数组检索方法(需遍历)
public User findUserById(String targetId, User[] array) {
    for (User user : array) {
        if (targetId.equals(user.getUserId())) {
            return user;
        }
    }
    return null;
}

3. 适配ExpandableListView

ExpandableListView需要分组数据和对应分组的子项数据,以下是通用实现步骤:

3.1 构建分组数据结构

这里以"按user_id首字母分组"为例,你可以根据需求调整分组规则:

Map<String, List<User>> groupData = new HashMap<>();
for (User user : userList) {
    // 取user_id首字母作为分组key
    String groupKey = user.getUserId().substring(0, 1).toUpperCase();
    if (!groupData.containsKey(groupKey)) {
        groupData.put(groupKey, new ArrayList<>());
    }
    groupData.get(groupKey).add(user);
}

// 提取分组标题的有序列表(ExpandableListView需要有序分组)
List<String> groupTitles = new ArrayList<>(groupData.keySet());
// 可选:对分组标题排序
Collections.sort(groupTitles);

3.2 自定义ExpandableListAdapter

public class UserExpandableAdapter extends BaseExpandableListAdapter {
    private Context context;
    private List<String> groupTitles;
    private Map<String, List<User>> groupUserMap;

    public UserExpandableAdapter(Context context, List<String> groupTitles, Map<String, List<User>> groupUserMap) {
        this.context = context;
        this.groupTitles = groupTitles;
        this.groupUserMap = groupUserMap;
    }

    @Override
    public int getGroupCount() {
        return groupTitles.size();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return groupUserMap.get(groupTitles.get(groupPosition)).size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        return groupTitles.get(groupPosition);
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return groupUserMap.get(groupTitles.get(groupPosition)).get(childPosition);
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(android.R.layout.simple_expandable_list_item_1, parent, false);
        }
        ((TextView) convertView.findViewById(android.R.id.text1)).setText(groupTitles.get(groupPosition));
        return convertView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_2, parent, false);
        }
        User user = (User) getChild(groupPosition, childPosition);
        TextView userIdTv = convertView.findViewById(android.R.id.text1);
        TextView emailTv = convertView.findViewById(android.R.id.text2);
        userIdTv.setText("用户ID: " + user.getUserId());
        emailTv.setText("邮箱: " + user.getEmail());
        return convertView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
}

3.3 绑定适配器到ListView

ExpandableListView expandableListView = findViewById(R.id.your_expandable_list_id);
UserExpandableAdapter adapter = new UserExpandableAdapter(this, groupTitles, groupData);
expandableListView.setAdapter(adapter);

补充说明

  • 若不需要分组,可将所有用户放入一个默认分组(比如"全部用户"),直接使用groupData.put("全部用户", userList)即可。
  • 确保Retrofit已配置Gson转换器(添加依赖implementation 'com.squareup.retrofit2:converter-gson:2.9.0'),否则无法自动解析JSON到模型类。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 20:05:40