Flutter测验应用从答案页跳转至题目页时如何正确自增题目计数?
问题根因
你的实现存在3个核心问题:
- 不能跨页面传递State类的setState方法,它是当前组件实例的上下文绑定方法,脱离对应组件调用必然报错
- 每次用
Navigator.push打开新页面会在路由栈堆叠新页面,多次跳转后会出现页面叠加、返回时跳转到旧答案页的问题,不符合「题目→答案→回到新题目」的交互逻辑 - 当前在选择答案后立刻调用了
quizList.nextQuestion(),导致进入答案页时题目索引已经自增,后续跳转逻辑完全混乱
具体修改方案
第一步:调整QuestionPage的参数和逻辑
去掉无用的setState参数,新增历史得分记录的传入入口,移除答题后立刻自增题目的逻辑:
import 'package:flutter/material.dart'; import '../screens/wrong_answer_page.dart'; import '../components/answer_button.dart'; import '../quiz_list.dart'; import 'correct_answer_page.dart'; QuizList quizList = QuizList(); class QuestionPage extends StatefulWidget { // 首次进入不传scoreKeeper时默认是空数组 const QuestionPage({super.key, this.scoreKeeper = const []}); final List<Icon> scoreKeeper; @override _QuestionPageState createState() => _QuestionPageState(); } class _QuestionPageState extends State<QuestionPage> { late List<Icon> scoreKeeper; @override void initState() { super.initState(); // 复制传入的历史得分记录,避免直接修改外部引用 scoreKeeper = List.from(widget.scoreKeeper); } void checkAnswer(String userPickedAnswer) { String correctAnswer = quizList.getQuestionAnswer(); if (userPickedAnswer == correctAnswer) { scoreKeeper.add( const Icon(Icons.circle_outlined, color: Colors.red), ); Navigator.push( context, MaterialPageRoute( builder: (context) => CorrectAnswerPage( scoreKeeper: scoreKeeper, // 传入下一题更新回调 onNextQuestion: () { setState(() { quizList.nextQuestion(); }); }))); } else { scoreKeeper.add( const Icon(Icons.close, color: Colors.blue), ); Navigator.push( context, MaterialPageRoute( builder: (context) => WrongAnswerPage( scoreKeeper: scoreKeeper, // 错误答案页也传入同样的回调 onNextQuestion: () { setState(() { quizList.nextQuestion(); }); }))); } // 删除此处原来的quizList.nextQuestion()调用 } @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Expanded( flex: 5, child: Padding( padding: const EdgeInsets.all(10.0), child: Center( child: Text( quizList.getQuestionText(), textAlign: TextAlign.center, style: const TextStyle( fontSize: 25.0, color: Colors.black, ), ), ), ), ), Expanded( child: Padding( padding: const EdgeInsets.all(15.0), child: AnswerButton( userPickedAnswer: 'a', onTap: () { setState(() { checkAnswer('a'); }); }), )), Expanded( child: Padding( padding: const EdgeInsets.all(15.0), child: AnswerButton( userPickedAnswer: 'b', onTap: () { setState(() { checkAnswer('b'); }); }), )), Expanded( child: Padding( padding: const EdgeInsets.all(15.0), child: AnswerButton( userPickedAnswer: 'c', onTap: () { setState(() { checkAnswer('c'); }); }), )), Expanded( child: Padding( padding: const EdgeInsets.all(15.0), child: AnswerButton( userPickedAnswer: 'd', onTap: () { setState(() { checkAnswer('d'); }); }), )), Row(children: scoreKeeper) ], ); } }
第二步:调整答案页的参数和跳转逻辑
给CorrectAnswerPage新增下一题回调参数,点击下一题时先触发回调更新题目索引,再返回上一级的题目页即可,不需要重新push新的题目页:
import 'package:flutter/material.dart'; import '../components/next_question_button.dart'; import '../quiz_list.dart'; class CorrectAnswerPage extends StatelessWidget { const CorrectAnswerPage({super.key, required this.scoreKeeper, required this.onNextQuestion}); final List<Icon> scoreKeeper; // 新增下一题回调参数 final VoidCallback onNextQuestion; @override Widget build(BuildContext context) { return Column( children: <Widget>[ Container( child: Center( child: const Text( 'correct', style: TextStyle( fontSize: 100, fontWeight: FontWeight.bold, color: Colors.red), ), ), ), const Divider( color: Colors.grey, indent: 16, endIndent: 16, ), const Text('EXPLANATION', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Colors.grey)), NextQuestionButton( onTap: () { // 先触发回调更新题目索引 onNextQuestion(); // 直接返回上一级的题目页,无需push新页面 Navigator.pop(context); }, ), Row( children: scoreKeeper, ) ], ); } }
WrongAnswerPage按照同样逻辑修改即可。
内容的提问来源于stack exchange,提问作者S C
相关产品推荐
相关产品推荐

