如何将数据传递到 initState 内定义的屏幕?

how to Pass data to a screen defined inside initState?

我试图制作一个带有两个随索引变化的视图的屏幕。 我像这样在 initState 中创建了 _pages 列表。

class AddPlan extends StatefulWidget {
  static const routeName = "addPlan";

  @override
  _AddPlanState createState() => _AddPlanState();
}

class _AddPlanState extends State<AddPlan> {
  List<Object>? _pages;
  int _selectedIndex = 0;
  Map<dynamic, dynamic> _stepVals = {};

  _setSelectedIndex(int newIndex, Map<dynamic, dynamic> newMap) {
    setState(() {
      _stepVals = {..._stepVals, ...newMap};
      _selectedIndex = newIndex;
    });
  }

  @override
  void initState() {
    // TODO: implement initState
    _pages = [
      StepOne(_setSelectedIndex),
      StepTwo(_stepVals, _setSelectedIndex)
    ];
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0,
        backgroundColor: Colors.transparent,
      ),
      body: Container(
        margin: EdgeInsets.only(top: 10),
        padding: EdgeInsets.symmetric(horizontal: 10),
        child: _pages![_selectedIndex] as Widget,
      ),
    );
  }
}

从 StepOne() 小部件我调用它来传递数据和更改索引。 widget.setNewIndex 是我的 _setSelectedIndex 函数。在我的 StepOne 构造函数中更改了名称。

ElevatedButton(
  onPressed: () {
    if (_formKey.currentState!.validate()) {
       _formKey.currentState!.save();
       widget.setNewIndex(1, {
         "title": title,
         "age": age,
         "description": description,
         "dificulty": _dificultyIndex,
         "targetMuscles": _targetMuscles,
         "weekDays": indexList,
        });
       }
     },
     child: Container(height: 50, child: Center(child: Text("Next"))),
)

这很好用。它更改了主屏幕内的 _stepVals 变量和 _selectedIndex。 它还将小部件更改为 StepTwo()。但是 StepTwo 小部件没有采用 _stepVals 的 nw 值。它似乎正在使用它在 initState 中收到的 _stepVals 的初始值。我在这里错过了什么吗?我是该语言的新手,所以请提供任何帮助。

您需要将此代码添加到您的 setState 或更高版本才能使其正常工作:

    setState(() {

      // You only need this:
      _pages = [
        StepOne(_setSelectedIndex),
        StepTwo(_stepVals, _setSelectedIndex)
      ];
      // Or this:
      _pages![1] = StepTwo(_stepVals, _setSelectedIndex);

      _stepVals = {..._stepVals, ...newMap};
      _selectedIndex = newIndex;
    });

因为 initState 不会在小部件重建时调用,它只会在第一次构建小部件时调用,所以您需要再次设置 StepTwo 小部件才能使其工作。


另一种方式:

您可以创建这样的函数:

  Widget getStep(int index) {
    switch (index) {
      case 0:
        return StepOne(index);
      case 1:
        return StepTwo(_stepVals, index);
    }
  }

然后将 getStep 添加到您的 build:

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0,
        backgroundColor: Colors.transparent,
      ),
      body: Container(
        margin: EdgeInsets.only(top: 10),
        padding: EdgeInsets.symmetric(horizontal: 10),
        child: getStep(_selectedIndex),
      ),
    );
  }

并使用你的 setState:

    setState(() {
      _stepVals = {..._stepVals, ...newMap};
      _selectedIndex = newIndex;
    });

您不需要 initState 任何变量。