我需要一些帮助来了解如何从继承的小部件中获取数据。
我通常使用
直接从build方法的小部件中获取参数 @override
Widget build(BuildContext context) {
//THIS METHOD
var data = StateContainer.of(context).data;
return Container(child:Text("${data.parameter}"));
}
但是由于还没有buildContext,所以不能从initState调用此方法。
我需要在initState方法中具有该参数(我在那从服务器中调用我的数据,并且需要将该数据传递给我的函数),那么,我该怎么做呢?
@override
void initState() {
otherData = fetchData(data);
super.initState();
}
我尝试使用didChangeDipendencies(),但每次重建视图时都会调用它(从屏幕弹出等),因此它不是我要使用的,也不是FutureBuilder小部件。
有什么建议吗?
答案 0 :(得分:1)
首先,请注意,您可能要做要使用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 :(得分:0)
1,如果仅需要 InheritedWidget 作为 Widget 的参数提供者。 您可以像下面这样在 initState 上使用
:@override
void initState() {
super.initState();
var data = context.ancestorInheritedElementForWidgetOfExactType(type)?.widget;
}
2,如果 InheritedWidget 的数据发生更改时,如果需要侦听器以重新呈现窗口小部件,则为
。建议您在 StatelessWidget 内包装 StatefulWidget , 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();
}
}
答案 2 :(得分:-1)
我更喜欢使用didChangeDependencies
的解决方案,因为Future.delayed
的解决方案有点破绽,看起来不专业且不健康。但是,它开箱即用。
这是我更喜欢的解决方案:
class _MyAppState extends State<MyApp> {
bool isDataLoaded = false;
@override
void didChangeDependencies() {
if (!isDataLoaded) {
otherData = fetchData(data).then((_){
this.isDataLoaded = true;
});
}
super.didChangeDependencies();
}
...
答案 3 :(得分:-2)
您还可以在initState中获取上下文,尝试使用持续时间为零的Future。您可以找到一些示例here
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')),
],
));
});
}
我用它来使用继承的窗口小部件来加载屏幕,并避免一些全局变量