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

从Firebase实时数据库获取嵌套数据并按科目分组展示问题

问题排查与解决方案

核心问题分析

  1. 数据模型设计缺陷:原showDataCustomLayout仅能存储单条测试数据,无法承载「科目-多个测试」的层级结构,不符合需求逻辑。
  2. Firebase数据读取不完整:仅读取了科目名称,未遍历每个科目下的测试数据,且读取完成后未通知适配器刷新列表。
  3. 布局与适配器不匹配:原布局和适配器仅适配单条测试数据,无法实现「一个CardView对应一个科目,内部包含多个测试项」的嵌套展示效果。

解决方案步骤

1. 重构数据模型类

创建支持层级结构的模型,每个科目包含对应的测试列表:

public class SubjectMarks {
    private String subjectName;
    private List<TestMark> testMarks;

    public SubjectMarks(String subjectName, List<TestMark> testMarks) {
        this.subjectName = subjectName;
        this.testMarks = testMarks;
    }

    public String getSubjectName() {
        return subjectName;
    }

    public List<TestMark> getTestMarks() {
        return testMarks;
    }

    // 内部类存储单条测试数据
    public static class TestMark {
        private String testName;
        private String marks;

        public TestMark(String testName, String marks) {
            this.testName = testName;
            this.marks = marks;
        }

        public String getTestName() {
            return testName;
        }

        public String getMarks() {
            return marks;
        }
    }
}

2. 修正Firebase数据读取逻辑

完整读取每个科目下的测试数据,并通知适配器更新:

private void showingMarks(String id) {
    final ArrayList<SubjectMarks> subjectList = new ArrayList<>();
    final MarksArrayAdapter adapter = new MarksArrayAdapter(this, subjectList);
    showSubjectListView.setAdapter(adapter);

    databaseReference.child("Student Marks/" + id).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            if (snapshot.exists()) {
                subjectList.clear();
                for (DataSnapshot subjectSnapshot : snapshot.getChildren()) {
                    String subjectName = subjectSnapshot.getKey();
                    List<SubjectMarks.TestMark> testList = new ArrayList<>();

                    // 遍历当前科目下的所有测试数据
                    for (DataSnapshot testSnapshot : subjectSnapshot.getChildren()) {
                        String testName = testSnapshot.getKey();
                        String marks = testSnapshot.getValue(String.class);
                        testList.add(new SubjectMarks.TestMark(testName, marks));
                    }

                    subjectList.add(new SubjectMarks(subjectName, testList));
                }
                adapter.notifyDataSetChanged(); // 通知适配器刷新数据
            }
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            Log.e("FirebaseError", error.getMessage());
        }
    });
}

3. 重写自定义适配器

适配新的层级模型,动态添加测试项到科目Card内:

public class MarksArrayAdapter extends ArrayAdapter<SubjectMarks> {
    public MarksArrayAdapter(@NonNull Context context, ArrayList<SubjectMarks> subjectList) {
        super(context, 0, subjectList);
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        ViewHolder holder;

        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.subject_card_layout, parent, false);
            holder = new ViewHolder();
            holder.subjectNameTv = convertView.findViewById(R.id.subjectName);
            holder.testContainer = convertView.findViewById(R.id.test_container);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        SubjectMarks currentSubject = getItem(position);
        if (currentSubject != null) {
            holder.subjectNameTv.setText(currentSubject.getSubjectName());
            holder.testContainer.removeAllViews();

            // 动态添加每个测试项到容器
            for (SubjectMarks.TestMark testMark : currentSubject.getTestMarks()) {
                View testItemView = LayoutInflater.from(getContext()).inflate(R.layout.test_marks_item, holder.testContainer, false);
                TextView testNameTv = testItemView.findViewById(R.id.test_number);
                TextView marksTv = testItemView.findViewById(R.id.test_marks);

                testNameTv.setText(testMark.getTestName());
                marksTv.setText(testMark.getMarks());

                holder.testContainer.addView(testItemView);
            }
        }

        return convertView;
    }

    // ViewHolder优化列表性能
    private static class ViewHolder {
        TextView subjectNameTv;
        LinearLayout testContainer;
    }
}

4. 调整布局文件

  • 科目Card布局(subject_card_layout.xml):
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="20dp"
    app:cardCornerRadius="10dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dp">

        <TextView
            android:id="@+id/subjectName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Subject"
            android:textColor="#707BFE"
            android:textSize="20sp"
            android:textStyle="bold" />

        <!-- 动态添加测试项的容器 -->
        <LinearLayout
            android:id="@+id/test_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" />

    </LinearLayout>

</androidx.cardview.widget.CardView>
  • 测试项布局(test_marks_item.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="horizontal"
    android:padding="8dp">

    <TextView
        android:id="@+id/test_number"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="Test 1"
        android:textAlignment="center"
        android:textColor="@color/black"
        android:textSize="16sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/test_marks"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="85"
        android:textAlignment="center"
        android:textColor="@color/black"
        android:textSize="16sp"
        android:textStyle="bold" />

</LinearLayout>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 00:24:57