Stateful Widget第二次导航时无法正常工作。

huangapple go评论106阅读模式
英文:

Stateful Widget Not Working Properly The Second Time It Is Navigated To

问题

当我运行以下程序时,第一次进入BoardView小部件时,它按预期工作。第二次进入BoardView小部件时,计算机玩家的AlertDialog与人类玩家的AlertDialog同时出现。

以下是您犯的错误:

  1. Round类的currentIndex属性未初始化: 在Round类中,currentIndex属性的初始值为-1,但在第一次调用changeTurn()方法之前,它没有被正确初始化。
Round({required this.currentIndex}) : handNo = 0 {
  // 在构造函数中为 currentIndex 设置初始值
  if (currentIndex == -1) {
    currentIndex = 0;
  }
}
  1. 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:

Stateful Widget第二次导航时无法正常工作。

And the following image shows what occurs the second time BoardView is entered through the _RoundInfoState.BoardView Entered Through The _RoundInfoState:

Stateful Widget第二次导航时无法正常工作。

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

huangapple
  • 本文由 发表于 2023年8月10日 10:39:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76872335.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定