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
相关产品推荐
相关产品推荐

