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的操作,因为您可以在构建方法之外访问上下文
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;
}
});
}