Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter flatter:从Widget';s州';初始状态_Flutter - Fatal编程技术网

Flutter flatter:从Widget';s州';初始状态

Flutter flatter:从Widget';s州';初始状态,flutter,Flutter,我有一个StatefulWidget,我想在命名路由中使用它。我必须通过一些论点,我正在做的建议,即 我不想将该逻辑放在build方法中,因为build可以被多次调用,并且初始化只需要发生一次。我可以将整个逻辑放在一个带有布尔isInitialized标志的块中,但这似乎不是正确的方法。 到目前为止,这个需求/案例在flift中不受支持吗?您可以使用新的PageRoute调用push,而不是通过pushNamed发送参数 假设您的参数类型称为参数。以下是有状态小部件及其状态类的外观: class

我有一个
StatefulWidget
,我想在命名路由中使用它。我必须通过一些论点,我正在做的建议,即

我不想将该逻辑放在
build
方法中,因为
build
可以被多次调用,并且初始化只需要发生一次。我可以将整个逻辑放在一个带有布尔isInitialized标志的块中,但这似乎不是正确的方法。
到目前为止,这个需求/案例在flift中不受支持吗?

您可以使用新的PageRoute调用push,而不是通过pushNamed发送参数

假设您的参数类型称为参数。以下是有状态小部件及其状态类的外观:

class YourStatefulWidget extends StatefulWidget {
    final Argument argument;

    YourStatefulWidget({
        @required this.argument,
    });

    @override
    State<StatefulWidget> createState() {
        return YourStatefulWidgetState();
    }
}

class YourStatefulWidgetState extends State<YourStatefulWidget> {

    @override
    initState() {
        super.initState();

        // Refer to your argument here by "widget.argument"

    }
}

使用
MaterialApp.ongeneraterout
属性,如下所示:

onGenerateRoute: (RouteSettings settings) {
  print('build route for ${settings.name}');
  var routes = <String, WidgetBuilder>{
    "hello": (ctx) => Hello(settings.arguments),
    "other": (ctx) => SomeWidget(),
  };
  WidgetBuilder builder = routes[settings.name];
  return MaterialPageRoute(builder: (ctx) => builder(ctx));
},
var = args;
_yourFunction(args) async {
// whatever you want to do
}

@override
  void initState() {
    super.initState();
    // future that allows us to access context. function is called inside the future
    // otherwise it would be skipped and args would return null
    Future.delayed(Duration.zero, () {
      setState(() {
        args = ModalRoute.of(context).settings.arguments;
      });
      print(args['id']);
      _yourFunction(args);
    });
  }

这里有一些测试
Hello
小部件:

class Hello extends StatelessWidget {
  final String greet;

  Hello(this.greet);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Text(
          'hello $greet',
          textScaleFactor: 5.0,
        ),
      ),
    );
  }
}

我只是遇到了和你一样的问题,并提出了一个解决方案。与使用onGenerateRoute不同,您仍然可以使用pushNamed Navigator来传递参数,并且您仍然可以在initState中访问ModalRoute参数-下面介绍了如何:

1) 在initState中使用future来访问上下文

  • 您可以使用
    Future.delayed(Duration.zero,(){})
  • 这使您可以访问上下文,还可以使用它在initState中执行类似showDialog的操作,因为您可以在构建方法之外访问上下文
2) 使用
ModalRoute.of(context.settings.arguments)提取参数

  • 在将来,提取参数并将它们存储在一个声明的、但未初始化的变量中,该变量是在initState之前创建的,但显然仍然在State对象中
  • 一旦你有了参数,你就可以用它们做任何你想做的事情,比如把变量传递到函数中
  • 重要提示:您必须使用future函数体内部的变量,否则颤振将跳过future(按其编程方式),并首先完成外部的任何操作,因此您的var仍将返回null,因为future尚未解析为给var一个值
总的来说,它看起来是这样的:

onGenerateRoute: (RouteSettings settings) {
  print('build route for ${settings.name}');
  var routes = <String, WidgetBuilder>{
    "hello": (ctx) => Hello(settings.arguments),
    "other": (ctx) => SomeWidget(),
  };
  WidgetBuilder builder = routes[settings.name];
  return MaterialPageRoute(builder: (ctx) => builder(ctx));
},
var = args;
_yourFunction(args) async {
// whatever you want to do
}

@override
  void initState() {
    super.initState();
    // future that allows us to access context. function is called inside the future
    // otherwise it would be skipped and args would return null
    Future.delayed(Duration.zero, () {
      setState(() {
        args = ModalRoute.of(context).settings.arguments;
      });
      print(args['id']);
      _yourFunction(args);
    });
  }


如果routeName没有那么重要,这对我来说是一个很好的方法

Navigator.push(
    context,
    MaterialPageRoute(
        builder: (_) => MySecondaryPage(requiredAttrib: myValue),
    ),
);
然后在您的小部件中,显然这只是一个在initState上使用TextEditingController的愚蠢用例:

class MySecondaryPage extends StatefulWidget {
  final requiredAttrib;

  MySecondaryPage({this.requiredAttrib});

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

class _MySecondaryPageState extends State<MySecondaryPage> {

    TextEditingController _myController = TextEditingController();

    @override
    void initState() { 
      super.initState();
      _myController.text = widget.requiredAttrib;
      ...
    }

  @override
  Widget build(BuildContext context) {
    return TextField(
        controller: _myController,
        ...
    );
  }
}
类MySecondaryPage扩展StatefulWidget{
最终要求的属性;
MySecondaryPage({this.requiredAttrib});
@凌驾
_MySecondaryPageState createState()=>\u MySecondaryPageState();
}
类_MySecondaryPageState扩展状态{
TextEditingController_myController=TextEditingController();
@凌驾
void initState(){
super.initState();
_myController.text=widget.requiredAttrib;
...
}
@凌驾
小部件构建(构建上下文){
返回文本字段(
控制器:_myController,
...
);
}
}

您可以在构造函数中使用传递de参数的命名路由

   routes: {
    '/hello': (context) => Hello(
          argument: ModalRoute.of(context).settings.arguments,
        ),
  },
然后在你的小部件中

 class Hello extends StatefulWidget {
  final argument;

  MySecondaryPage({this.argument});

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

我用WidgetsBinding。它可以在initState内部调用,并且在构建小部件完成渲染后只调用一次

@override
void initState() {
   super.initState();

   final widgetsBinding = WidgetsBinding.instance;
   widgetsBinding.addPostFrameCallback((callback) {
  if (ModalRoute.of(context).settings.arguments != null) {
    _currentIndex = ModalRoute.of(context).settings.arguments;
  }
 });
}

我需要使用PushName还有其他原因(比如说使用PopTill),否则你的建议显然是直截了当的,应该是第一选择。很好的最小方法。很棒的兄弟!在这里粘贴答案@pskink ongeneraterout似乎很合适。我没有考虑过。你可以把这个作为回答,这样我就可以接受了。总的来说,onGenerateRoute似乎更方便。它也可以与initialRoute一起使用,这在页面上给出的示例中不清楚。颤振食谱建议使用onGenerateRoute。OnGeneratorOute就是为了这个目的而存在的。使用它比使用这种过于复杂的状态黑客更好。在下面的一行中,如果您不通过
设置
,路由URL将不会出现在web中:return materialpage(builder:(ctx)=>builder(ctx),settings:settings;那么
didChangeDependencies
呢。当上下文发生变化时,有什么理由不在init函数之后调用该函数?
 class Hello extends StatefulWidget {
  final argument;

  MySecondaryPage({this.argument});

  @override
  _MySecondaryPageState createState() => _MySecondaryPageState();
}
@override
void initState() {
   super.initState();

   final widgetsBinding = WidgetsBinding.instance;
   widgetsBinding.addPostFrameCallback((callback) {
  if (ModalRoute.of(context).settings.arguments != null) {
    _currentIndex = ModalRoute.of(context).settings.arguments;
  }
 });
}