Dart代码中尝试次数不足时切换页面报错:需传入BuildContext参数
问题根源
你的Spiel_nummer是普通业务逻辑类,本身不持有Flutter的BuildContext,而Navigator必须依赖上下文才能完成页面跳转,所以直接在类里调用Navigator.push会报错。
解决方案
方案一:直接传递BuildContext参数
修改gameover方法,让它接收BuildContext,同时在调用guessnumber时传入上下文:
- 修改
Spiel_nummer类的方法:
class Spiel_nummer { Random random = new Random(); int trys = 5; int random_number = 0; int lastguess = 0; dynamic ico = null; int score = 0; int generate_random_number() => random.nextInt(101); bool guessnumber(int number, BuildContext context) { print(number); if (number == random_number) { reset(); score++; return true; } else { trys--; if (number < random_number) { lastguess = 0; ico = Icons.arrow_upward; } else if (number > random_number) { lastguess = 1; ico = Icons.arrow_downward; } if (trys <= 0) { gameover(context); score = 0; reset(); } return false; } } void gameover(BuildContext context){ Navigator.push(context, MaterialPageRoute(builder: (context) => MyApp())); } void reset() { trys = 5; random_number = generate_random_number(); } }
- 在UI层调用时传入上下文:
// 假设在State类的按钮点击事件中 ElevatedButton( onPressed: () { int inputNumber = int.parse(_inputController.text); spiel.guessnumber(inputNumber, context); }, child: const Text("猜数字"), )
方案二:用回调函数解耦(推荐)
让业务类和UI层解耦,通过回调通知UI层处理页面跳转,避免业务类依赖BuildContext:
- 修改
Spiel_nummer类,添加游戏结束回调:
import 'package:flutter/material.dart'; class Spiel_nummer { Random random = new Random(); int trys = 5; int random_number = 0; int lastguess = 0; dynamic ico = null; int score = 0; // 定义游戏结束回调 VoidCallback? onGameOver; int generate_random_number() => random.nextInt(101); bool guessnumber(int number) { print(number); if (number == random_number) { reset(); score++; return true; } else { trys--; if (number < random_number) { lastguess = 0; ico = Icons.arrow_upward; } else if (number > random_number) { lastguess = 1; ico = Icons.arrow_downward; } if (trys <= 0) { onGameOver?.call(); score = 0; reset(); } return false; } } void reset() { trys = 5; random_number = generate_random_number(); } }
- 在UI层初始化时绑定回调:
class GamePage extends StatefulWidget { const GamePage({super.key}); @override State<GamePage> createState() => _GamePageState(); } class _GamePageState extends State<GamePage> { final Spiel_nummer spiel = Spiel_nummer(); final _inputController = TextEditingController(); @override void initState() { super.initState(); // 绑定游戏结束回调 spiel.onGameOver = () { Navigator.push(context, MaterialPageRoute(builder: (context) => const MyApp())); }; // 初始化随机数 spiel.random_number = spiel.generate_random_number(); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TextField( controller: _inputController, keyboardType: TextInputType.number, decoration: const InputDecoration(hintText: "输入数字"), ), const SizedBox(height: 20), ElevatedButton( onPressed: () { int inputNumber = int.parse(_inputController.text); spiel.guessnumber(inputNumber); }, child: const Text("猜数字"), ), ], ), ), ); } }
说明
方案二更符合单一职责原则,业务类只负责处理游戏逻辑,页面跳转交给UI层处理,代码更易维护和测试。如果是简单场景,方案一也能快速解决问题。
内容的提问来源于stack exchange,提问作者Xandertime2222
相关产品推荐
相关产品推荐

