在 initState 中获取 InheritedWidget 参数
Get InheritedWidget parameter in initState
我需要一些帮助来了解如何从继承的小部件获取数据。
我通常使用
直接从构建方法中获取小部件的参数
@override
Widget build(BuildContext context) {
//THIS METHOD
var data = StateContainer.of(context).data;
return Container(child:Text("${data.parameter}"));
}
但是这个方法不能从 initState 调用,因为还没有 buildContext。
我需要在 initState 方法中包含该参数(我在其中调用从服务器获取数据,我需要将该数据传递给我的函数),那么,我应该怎么做?
@override
void initState() {
otherData = fetchData(data);
super.initState();
}
我尝试使用 didChangeDipendencies() 但每次重建视图(从屏幕弹出等)时都会调用它,所以它不是我想要使用的,也不是 FutureBuilder 小部件。
有什么建议吗?
您还可以在 initState 中获取上下文,尝试使用持续时间为零的未来。你可以找到一些例子
void initState() {
super.initState();
Future.delayed(Duration.zero,() {
//use context here
showDialog(context: context, builder: (context) => AlertDialog(
content: Column(
children: <Widget>[
Text('@todo')
],
),
actions: <Widget>[
FlatButton(onPressed: (){
Navigator.pop(context);
}, child: Text('OK')),
],
));
});
}
我用它来使用继承的小部件制作加载屏幕并避免一些全局变量
我更喜欢 didChangeDependencies
的解决方案,因为 Future.delayed
的解决方案有点 hack,看起来不专业且不健康。但是,它开箱即用。
这是我更喜欢的解决方案:
class _MyAppState extends State<MyApp> {
bool isDataLoaded = false;
@override
void didChangeDependencies() {
if (!isDataLoaded) {
otherData = fetchData(data).then((_){
this.isDataLoaded = true;
});
}
super.didChangeDependencies();
}
...
首先,请注意您可能 想要使用 didChangeDependencies
。但是你不能不经任何检查就在那里打电话。您需要先将其包装在 if
中。
典型的 didChangeDependencies
实现应该类似于:
Foo foo;
@override
void didChangeDependencies() {
super.didChangeDependencies();
final foo = Foo.of(context);
if (this.foo != foo) {
this.foo = foo;
foo.doSomething();
}
}
使用这样的代码,doSomething
将在foo
更改时仅 执行。
或者,如果您很懒惰并且确信您的对象永远不会改变,那么还有另一种解决方案。
获取InheritedWidget,通常使用的方法是:
BuildContext context;
InheritedWidget foo = context.inheritFromWidgetOfExactType(Foo);
而且在initState
.
里面不能调用的就是这个方法
但是还有另一种方法可以做同样的事情:
BuildContext context;
InheritedWidget foo = context.ancestorInheritedElementForWidgetOfExactType(Foo)?.widget;
扭曲是:
- 这个方法可以在内部调用 initState
- 它不会处理值更改的情况。
因此,如果您的值永远不会改变,您可以改用它。
1、如果你只需要InheritedWidget作为Widget的参数提供者。
您可以在 initState 上使用,如下所示:
@override
void initState() {
super.initState();
var data = context.ancestorInheritedElementForWidgetOfExactType(type)?.widget;
}
2、当InheritedWidget数据变化时,如果需要监听re-renderwidget。我建议你把你的 StatefulWidget insider 包装成 StatelessWidget,
StatefulWidget的参数是从StatelessWidget传过来的,当InheritedWidget改变数据时,会通知给StatelessWidget,在 StatefulWidget 上,我们将在 didChangeDependencies 上进行更改,您可以刷新数据。
这是代码指南:
class WrapperDemoWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
DemoData data = StateContainer.of(context).data;
return Container();
}
}
class ImplementWidget extends StatefulWidget {
DemoData data;
ImplementWidget({this.data});
@override
_ImplementWidgetState createState() => _ImplementWidgetState();
}
class _ImplementWidgetState extends State<ImplementWidget> {
@override
void initState() {
super.initState();
//TODO Do sth with widget.data
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
//TODO Do change with widget.data
}
@override
Widget build(BuildContext context) {
return Container();
}
}
我需要一些帮助来了解如何从继承的小部件获取数据。
我通常使用
直接从构建方法中获取小部件的参数 @override
Widget build(BuildContext context) {
//THIS METHOD
var data = StateContainer.of(context).data;
return Container(child:Text("${data.parameter}"));
}
但是这个方法不能从 initState 调用,因为还没有 buildContext。
我需要在 initState 方法中包含该参数(我在其中调用从服务器获取数据,我需要将该数据传递给我的函数),那么,我应该怎么做?
@override
void initState() {
otherData = fetchData(data);
super.initState();
}
我尝试使用 didChangeDipendencies() 但每次重建视图(从屏幕弹出等)时都会调用它,所以它不是我想要使用的,也不是 FutureBuilder 小部件。
有什么建议吗?
您还可以在 initState 中获取上下文,尝试使用持续时间为零的未来。你可以找到一些例子
void initState() {
super.initState();
Future.delayed(Duration.zero,() {
//use context here
showDialog(context: context, builder: (context) => AlertDialog(
content: Column(
children: <Widget>[
Text('@todo')
],
),
actions: <Widget>[
FlatButton(onPressed: (){
Navigator.pop(context);
}, child: Text('OK')),
],
));
});
}
我用它来使用继承的小部件制作加载屏幕并避免一些全局变量
我更喜欢 didChangeDependencies
的解决方案,因为 Future.delayed
的解决方案有点 hack,看起来不专业且不健康。但是,它开箱即用。
这是我更喜欢的解决方案:
class _MyAppState extends State<MyApp> {
bool isDataLoaded = false;
@override
void didChangeDependencies() {
if (!isDataLoaded) {
otherData = fetchData(data).then((_){
this.isDataLoaded = true;
});
}
super.didChangeDependencies();
}
...
首先,请注意您可能 想要使用 didChangeDependencies
。但是你不能不经任何检查就在那里打电话。您需要先将其包装在 if
中。
典型的 didChangeDependencies
实现应该类似于:
Foo foo;
@override
void didChangeDependencies() {
super.didChangeDependencies();
final foo = Foo.of(context);
if (this.foo != foo) {
this.foo = foo;
foo.doSomething();
}
}
使用这样的代码,doSomething
将在foo
更改时仅 执行。
或者,如果您很懒惰并且确信您的对象永远不会改变,那么还有另一种解决方案。
获取InheritedWidget,通常使用的方法是:
BuildContext context;
InheritedWidget foo = context.inheritFromWidgetOfExactType(Foo);
而且在initState
.
但是还有另一种方法可以做同样的事情:
BuildContext context;
InheritedWidget foo = context.ancestorInheritedElementForWidgetOfExactType(Foo)?.widget;
扭曲是:
- 这个方法可以在内部调用 initState
- 它不会处理值更改的情况。
因此,如果您的值永远不会改变,您可以改用它。
1、如果你只需要InheritedWidget作为Widget的参数提供者。 您可以在 initState 上使用,如下所示:
@override
void initState() {
super.initState();
var data = context.ancestorInheritedElementForWidgetOfExactType(type)?.widget;
}
2、当InheritedWidget数据变化时,如果需要监听re-renderwidget。我建议你把你的 StatefulWidget insider 包装成 StatelessWidget, StatefulWidget的参数是从StatelessWidget传过来的,当InheritedWidget改变数据时,会通知给StatelessWidget,在 StatefulWidget 上,我们将在 didChangeDependencies 上进行更改,您可以刷新数据。 这是代码指南:
class WrapperDemoWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
DemoData data = StateContainer.of(context).data;
return Container();
}
}
class ImplementWidget extends StatefulWidget {
DemoData data;
ImplementWidget({this.data});
@override
_ImplementWidgetState createState() => _ImplementWidgetState();
}
class _ImplementWidgetState extends State<ImplementWidget> {
@override
void initState() {
super.initState();
//TODO Do sth with widget.data
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
//TODO Do change with widget.data
}
@override
Widget build(BuildContext context) {
return Container();
}
}