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

Android开发新手求助:含子项的JSON适配SimpleAdapter与AsyncTask问题

搞定带回复的评论列表:别用嵌套ListView,试试这招!

兄弟,我太懂你这种卡壳的滋味了——折腾好几天,数据能拿到就是显示不出来,对着带嵌套的JSON抓头发,搜了一堆资料还是没头绪,简直崩溃😤

先给你划重点:别用ListView嵌套ListView!这种方案看似直观,但会带来严重的性能问题,滚动时卡顿、复用混乱都是常有的事,Android官方也不推荐这种嵌套滚动的实现方式。针对你这种「评论+子回复」的层级结构,有两个更靠谱的选择,我给你一步步拆解:

第一步:先把JSON数据映射成Java对象

首先得把杂乱的JSON转换成清晰的实体类,方便后续操作。根据你给的JSON示例,我们可以定义两个类:

Comment(评论类)

public class Comment {
    private String comentariosId;
    private String noticiasId;
    private String content; // 假设评论内容字段叫这个,你可以根据实际JSON调整
    private List<Reply> replies; // 存储该评论下的所有回复

    // 构造方法、getter、setter自己补全哈
}

Reply(回复类)

public class Reply {
    private String replyId;
    private String commentId;
    private String content;

    // 同样补全构造方法、getter、setter
}

然后在AsyncTask的doInBackground里解析JSON:

@Override
protected List<Comment> doInBackground(Void... voids) {
    List<Comment> commentList = new ArrayList<>();
    try {
        JSONObject jsonObject = new JSONObject(你的JSON字符串);
        JSONArray comentariosArray = jsonObject.getJSONArray("COMENTARIOS");

        for (int i = 0; i < comentariosArray.length(); i++) {
            JSONObject commentObj = comentariosArray.getJSONObject(i);
            Comment comment = new Comment();
            comment.setComentariosId(commentObj.getString("comentarios_id"));
            comment.setNoticiasId(commentObj.getString("noticias_id"));
            // 其他评论字段同理

            // 解析回复(假设回复字段叫RESPUESTAS,你根据实际JSON调整)
            if (commentObj.has("RESPUESTAS")) {
                JSONArray repliesArray = commentObj.getJSONArray("RESPUESTAS");
                List<Reply> replyList = new ArrayList<>();
                for (int j = 0; j < repliesArray.length(); j++) {
                    JSONObject replyObj = repliesArray.getJSONObject(j);
                    Reply reply = new Reply();
                    reply.setReplyId(replyObj.getString("respuestas_id")); // 示例字段,按需调整
                    reply.setContent(replyObj.getString("content"));
                    replyList.add(reply);
                }
                comment.setReplies(replyList);
            }
            commentList.add(comment);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return commentList;
}

第二步:选对列表组件,两种方案任你挑

方案一:用ExpandableListView(新手友好)

这个组件天生就是为「父项+子项」的层级结构设计的,不用自己处理嵌套滚动的坑,实现起来最简单:

  1. 布局文件:在你的Activity布局里加入ExpandableListView
<ExpandableListView
    android:id="@+id/expandable_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
  1. 写父项(评论)和子项(回复)的布局:

    • 评论布局(item_comment.xml):放评论的内容、时间、作者这些元素
    • 回复布局(item_reply.xml):样式可以比评论稍缩进,区分层级
  2. 自定义ExpandableListAdapter:

public class CommentExpandableAdapter extends BaseExpandableListAdapter {
    private Context mContext;
    private List<Comment> mCommentList;

    public CommentExpandableAdapter(Context context, List<Comment> commentList) {
        this.mContext = context;
        this.mCommentList = commentList;
    }

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

    @Override
    public int getChildrenCount(int groupPosition) {
        Comment comment = mCommentList.get(groupPosition);
        return comment.getReplies() != null ? comment.getReplies().size() : 0;
    }

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

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return mCommentList.get(groupPosition).getReplies().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(mContext).inflate(R.layout.item_comment, parent, false);
        }
        Comment comment = (Comment) getGroup(groupPosition);
        // 绑定评论数据到布局控件,比如TextView显示内容
        TextView commentContent = convertView.findViewById(R.id.tv_comment_content);
        commentContent.setText(comment.getContent());
        // 其他字段同理
        return convertView;
    }

    // 渲染回复子项
    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_reply, parent, false);
        }
        Reply reply = (Reply) getChild(groupPosition, childPosition);
        TextView replyContent = convertView.findViewById(R.id.tv_reply_content);
        replyContent.setText(reply.getContent());
        return convertView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true; // 允许点击回复项
    }
}
  1. 在AsyncTask的onPostExecute里设置Adapter:
@Override
protected void onPostExecute(List<Comment> commentList) {
    super.onPostExecute(commentList);
    ExpandableListView expandableListView = findViewById(R.id.expandable_list);
    CommentExpandableAdapter adapter = new CommentExpandableAdapter(YourActivity.this, commentList);
    expandableListView.setAdapter(adapter);
}

方案二:用RecyclerView(更灵活)

如果以后需要更复杂的交互(比如评论点赞、回复输入),RecyclerView会更灵活。你可以:

  • 给每个评论Item里嵌套一个小的RecyclerView来显示回复,但要注意给这个子RecyclerView设置固定高度,或者用NestedScrollView配合recyclerView.setNestedScrollingEnabled(false)来避免滚动冲突。
  • 或者用多类型Item,把评论和回复都当成不同类型的Item,通过位置来判断层级(但需要自己处理缩进和布局区分)。不过这个方案对新手来说稍复杂,先把ExpandableListView搞懂再尝试也不迟。

最后提个醒

你之前用的SimpleAdapter只适合扁平的一维数据,没法处理这种嵌套结构,所以必须自定义Adapter才行。另外AsyncTask现在已经被官方标记为过时了,新项目里可以考虑用Coroutines或者ExecutorService来做异步任务,但你现在先把功能跑通,后续再优化也没问题。

按这个步骤来,应该能搞定你的评论列表了,加油!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:54:45