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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 04:15:02