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

Flutter PageView.builder嵌套对象列表渲染问题排查

问题排查

你的代码无法正常渲染选项核心是3个问题:

  • 数据初始化错误:构建questionList时,option参数传的是Option类本身,不是实例化的选项对象,和你单独定义的optionList没有任何关联,自然读不到a/b/c/d的具体值。
  • 数据结构设计不合理:题目和选项是一对一的绑定关系,拆成两个独立列表维护,后续只要增删题目很容易出现索引错位、选项和题目匹配错误的问题。
  • 多余布局嵌套:代码里写了两层无意义的嵌套Column,虽然不会直接导致数据不显示,但很容易引发布局约束异常。
可行实现方案

1. 先定义规范的数据模型

所有属性标记为必填,从根源上避免空值异常:

class Option {
  final String a;
  final String b;
  final String c;
  final String d;

  Option({
    required this.a,
    required this.b,
    required this.c,
    required this.d,
  });
}

class QuestionModel {
  final String id;
  final String qtn;
  final Option option;

  QuestionModel({
    required this.id,
    required this.qtn,
    required this.option,
  });

  // 如果需要从JSON转模型,加这个工厂方法,避免手写赋值出错
  factory QuestionModel.fromJson(Map<String, dynamic> json) {
    return QuestionModel(
      id: json['id'] as String,
      qtn: json['qtn'] as String,
      option: Option(
        a: json['option']['a'] as String,
        b: json['option']['b'] as String,
        c: json['option']['c'] as String,
        d: json['option']['d'] as String,
      ),
    );
  }
}

2. 初始化正确的嵌套题目列表

直接把选项实例嵌套进每个题目对象,不需要单独维护optionList:

List<QuestionModel> questionList = [
  QuestionModel(
    id: "001",
    qtn: "In how many ways can a committee of 4 people be chosen out of 8 people?",
    option: Option(a: "32", b: "52", c: "70", d: "79"),
  ),
  QuestionModel(
    id: "002",
    qtn: "In how many ways, a committee of 6 members be selected from 7 men and 5 ladies, consisting of 4 men and 2 ladies?",
    option: Option(a: "250", b: "350", c: "450", d: "550"),
  ),
  QuestionModel(
    id: "003",
    qtn: "A committee of 5 members is to be formed by selecting out 4 men and 5 women. In how many different ways the committee can be formed if it should have 2 men and 3 women?",
    option: Option(a: "30", b: "60", c: "70", d: "80"),
  ),
  QuestionModel(
    id: "004",
    qtn: "In how many ways can a committee of 4 people be chosen out of 8 people?",
    option: Option(a: "32", b: "52", c: "70", d: "79"),
  ),
  QuestionModel(
    id: "005",
    qtn: "In how many ways can a committee of 4 people be chosen out of 8 people?",
    option: Option(a: "32", b: "52", c: "70", d: "79"),
  ),
  QuestionModel(
    id: "006",
    qtn: "In how many ways can a committee of 4 people be chosen out of 8 people?",
    option: Option(a: "32", b: "52", c: "70", d: "79"),
  ),
];

如果你的数据是从接口返回的JSON列表,直接用工厂方法批量转换即可,不用手动逐行写:

// 假设originalJsonList是接口返回的原始JSON数组
List<QuestionModel> questionList = (originalJsonList as List)
    .map((item) => QuestionModel.fromJson(item))
    .toList();

如果你一定要保留独立的optionList,初始化题目时必须按索引传入对应选项实例,比如第一题传option: optionList[0],第二题传option: optionList[1]。但这种写法维护成本极高,非常不建议使用。

3. 修正PageView.builder渲染逻辑

去掉多余的嵌套布局,直接读取当前题目的嵌套选项属性渲染:

Flexible(
  fit: FlexFit.tight,
  child: PageView.builder(
    controller: homeViewModel.pageController,
    onPageChanged: homeViewModel.openNextIndex,
    itemCount: homeViewModel.questionList.length,
    itemBuilder: (context, index) {
      // 提前拿当前题目和选项,避免重复写长链代码
      final currentQuestion = homeViewModel.questionList[index];
      final currentOption = currentQuestion.option;
      return Container(
        padding: const EdgeInsets.symmetric(horizontal: 16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 题干渲染区域
            Container(
              height: SizeConfig.safeBlockVertical! * 16,
              alignment: Alignment.center,
              child: Text(
                currentQuestion.qtn,
                style: const TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.w500,
                ),
              ),
            ),
            SizedBox(height: AppSizes.large_dimension),
            // 选项渲染区域
            Text("A. ${currentOption.a}"),
            const SizedBox(height: 12),
            Text("B. ${currentOption.b}"),
            const SizedBox(height: 12),
            Text("C. ${currentOption.c}"),
            const SizedBox(height: 12),
            Text("D. ${currentOption.d}"),
          ],
        ),
      );
    },
  ),
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 03:27:26