英文:
Stateful Widget Not Working Properly The Second Time It Is Navigated To
问题
当我运行以下程序时,第一次进入BoardView小部件时,它按预期工作。第二次进入BoardView小部件时,计算机玩家的AlertDialog与人类玩家的AlertDialog同时出现。
以下是您犯的错误:
- Round类的currentIndex属性未初始化: 在Round类中,currentIndex属性的初始值为-1,但在第一次调用changeTurn()方法之前,它没有被正确初始化。
Round({required this.currentIndex}) : handNo = 0 {
// 在构造函数中为 currentIndex 设置初始值
if (currentIndex == -1) {
currentIndex = 0;
}
}
- Round类的changeTurn方法问题: 在changeTurn方法中,当currentIndex为-1时,将其更改为0可能会导致问题。在第一次进入时,currentIndex应该保持-1,以便在第一次调用changeTurn时将其更改为0。
void changeTurn() {
if (currentIndex != -1) {
currentIndex = currentIndex == 0 ? 1 : 0;
}
notifyListeners();
}
以上是您代码中的问题和相应的解决方案。请尝试进行这些更改并再次运行您的程序,看看是否解决了问题。
英文:
When I run the following program, it works as intended the first time I enter the BoardView widget. The second time I enter the BoardView widget, the AlertDialog for the computer player appears at the same time the human player's AlertDialog does.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
Round roundController = Round(currentIndex: -1);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
child: const Text("New Game",
style: TextStyle(fontSize: 50, color: Colors.black)),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
BoardView(roundController: widget.roundController)),
);
})));
}
}
class Round extends ChangeNotifier {
Round({required this.currentIndex}) : handNo = 0;
void changeTurn() {
if (currentIndex == -1) {
currentIndex = 0;
} else {
currentIndex = currentIndex == 0 ? 1 : 0;
}
notifyListeners();
}
int currentIndex, handNo;
}
class BoardView extends StatefulWidget {
Round roundController;
BoardView({Key? key, required this.roundController}) : super(key: key);
@override
_BoardViewState createState() => _BoardViewState();
}
class _BoardViewState extends State<BoardView> {
late List<String> players = ["Human", "Computer"];
late bool showButton;
void _playerTakesTurn() {
if (players[widget.roundController.currentIndex] == "Human") {
showDialogPopUp(
context,
"Human Player's Turn",
"It is time for you to take your turn.",
widget.roundController.handNo,
widget.roundController);
} else {
showDialogPopUp(
context,
"Computer Player's Tile Placement",
"The computer took their turn",
widget.roundController.handNo,
widget.roundController);
}
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => _playerTakesTurn());
widget.roundController.addListener(_playerTakesTurn);
}
@override
void dispose() {
widget.roundController.removeListener(_playerTakesTurn);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.teal[400],
);
}
}
Future<void> showDialogPopUp(BuildContext context, String title, String text,
int handNo, Round roundController) {
return showDialog<String>(
context: context,
builder: (BuildContext context) {
return AlertDialog(title: Text(title), content: Text(text), actions: [
TextButton(
child: const Text("OK"),
onPressed: () {
Navigator.of(context).pop();
roundController.changeTurn();
if (handNo == 2) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RoundInfo(
roundController: roundController,
)));
} else {
roundController.handNo++;
}
},
)
]);
});
}
class RoundInfo extends StatefulWidget {
final Round roundController;
const RoundInfo({Key? key, required this.roundController}) : super(key: key);
@override
State<RoundInfo> createState() => _RoundInfoState();
}
class _RoundInfoState extends State<RoundInfo> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.greenAccent[700],
body: Column(children: [
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BoardView(
roundController: widget.roundController)));
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
),
child: const Text('Proceed',
style: TextStyle(
color: Colors.black,
fontSize: 35,
fontWeight: FontWeight.bold))),
]));
}
}
The following image shows what occurs the first time BoardView is entered.First Time BoardView Is Entered:
And the following image shows what occurs the second time BoardView is entered through the _RoundInfoState.BoardView Entered Through The _RoundInfoState:
Please let me know what I am doing wrong here. Thank you.
答案1
得分: 0
基本上,这是因为您的应用生命周期中有一个Single
Round控制器,您在第一个屏幕中初始化了它Round roundController = Round(currentIndex: -1);
,每当用户转到BoardView
时,都会将新的监听器附加到相同的控制器上。
要解决此问题,只需将Round roundController = Round(currentIndex: -1);
从MyHomePage
移动到_MyHomePageState
,并修复widget.roundController
问题将会出现。
英文:
Basically this happens because you have a Single
Round controller in your app lifecycle, you initialized it in your first screen Round roundController = Round(currentIndex: -1);
and every time the user goes to BoardView
you attach a new listener to the same controller.
to solve this, simply move Round roundController = Round(currentIndex: -1);
from MyHomePage
to _MyHomePageState
and fix the widget.roundController
issue will appear
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论