我想显示一个条形图,其中我使用两个不同的提供程序作为源信息。
我最初的方法是使用未来的构建器,在获取数据时显示加载图标,然后操作该数据以满足我在图形中的需求。
因此,我使用了小部件中的未来构建器,在其中显示我的图形,并使用Future
对其进行初始化,该将从另一个可重用文件中获取上下文。
my_wdiget.dart
...
class _MyWidgetState extends State<MyWidget> {
late Future<List<MyObject>> myFutureVariable;
Future<List<MyObject>> _getMyObjects() async {
return getMyObjects(context);
}
@override
void initState() {
super.initState();
myFutureVariable= _getMyObjects();
}
...
FutureBuilder<List<MyObject>>(
future: myFutureVariable,
builder: (BuildContext context,
AsyncSnapshot<List<MyObject>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator())),
);
default:
if (snapshot.hasError) {
return Center(
child: Text('Error: ${snapshot.error}'))),
);
} else if (snapshot.data == null) {
return Center(
child:
Text('You don't have any item yet.'))),
);
} else {
return BarChart(
_getChartData(snapshot.data!),
),
);
}
}
},
),
这是我生成数据的文件:
my_object_utils.dart
Future<List<MyObject>> getMyObjects(BuildContext context) async {
await Future.delayed(Duration(seconds: 1)); // Simulation delayed query
var source1= Provider.of<MySource1>(context, listen: false).items;
var source2 = Provider.of<MySource2>(context, listen: false).otherItems;
List<MyObject> myObjects= [];
// Do some stuff to fill the myObjects using source1 and source2
return myObjects;
}
问题:
- 这种工作,但我从提供商的行中得到警告
use_build_context_synchronously
。 - 我想侦听更改,但是如果我设置了默认
listen: true
它将崩溃,告诉我更改该属性。
所以我的问题是,我怎样才能FutureBuilder
监听多个提供商的变化?
建议使用方法进行更新@hydra: 如果我有:
void test() {
print('a');
setState(() {});
}
Consumer2<MySource1, MySource1>(
builder: (context, sourceOne, sourceTwo, child) {
myFutureVariable = getMyObjects(sourceOne.items, sourceTwo.otherItems),
return FutureBuilder<List<MyObject>>(
future: myFutureVariable,
builder: (context, snapshot) {
...
else{
return child: ElevatedButton(
child: Text('a'),
onPressed: test,
);
}
}
),
},
),
每次按下按钮时,它都会触发setState
并且会出现circularProgressIndicator
,尽管消费者没有进行任何更改。
要解决这两个问题,您可以使用Consumer2
如果两个提供程序中的任何一个发生更改,FutureBuilder
将重新生成
Consumer2<MySource1, MySource1>(
builder: (context, sourceOne, sourceTwo, child) {
return FutureBuilder<List<MyObject>>(
future: myFutureVariable(sourceOne.items, sourceTwo.otherItems),
builder: (context, snapshot) {
// ...
}
),
},
),
并将函数更新为:
Future<List<MyObject>> getMyObjects(final items, final otherItems) async {
// use your items and otherItems here.
await Future.delayed(Duration(seconds: 1)); // just for testing, right?
List<MyObject> myObjects= [];
// Do some stuff to fill the myObjects using source1 and source2
return myObjects;
}