使用 FutureBuilder 时,Mobx Observer 无法按预期工作
Mobx Observer not working as expected when using FutureBuilder
当尝试在脚手架主体内创建项目的列表视图时,我无法使用 mobx(版本:0.3.5)在另一个地方(Appbar)更新该列表中项目数量的显示和 flutter_mobx(版本:0.3.0+1)。
我已经尝试使用 Provider 包 (3.0.0+1) 解决这个问题,但这也没有解决,所以我想我遗漏了一些关于 FutureBuilder 和 Flutter 构建过程的本质.
// the mobx-store
ItemTracker itemTracker = ItemTracker();
class StartPage extends StatefulWidget {
StartPageState createState() => StartPageState();
}
class StartPageState extends State<StartPage> {
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
// this Observer doesn't update
leading: Observer(
builder: (_) => Text('Items: ' + itemTracker.amount.toString())),
title: Text('MyApp',
style: TextStyle(
color: Colors.deepPurpleAccent[50],
fontSize: 16,
fontWeight: FontWeight.bold,
)),
centerTitle: true,
),
body: ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(20.0),
children: <Widget>[
FutureBuilder(
future: ApiService.getOffers(),
builder: (BuildContext context,
AsyncSnapshot<List<Offer>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator(),
);
default:
return snapshot.hasError
? Text('Error: ${snapshot.error}')
: _createOfferList(context, snapshot);
}
}),
],
),
),
);
}
Widget _createOfferList(BuildContext context, AsyncSnapshot snapshot) {
// after receiving the response, the amount of items should get written to
// itemTracker.amount - the Observer-part should be rerendered, but it won't
itemTracker.updateAmount(snapshot.data.length);
print(snapshot.data.length.toString());
return ListView.builder(
itemCount: snapshot.data.length,
shrinkWrap: true,
primary: false,
itemBuilder: (BuildContext context, int index) {
return Card(
color: Colors.lightBlue[50],
child: ListTile(
leading: Image.asset(snapshot.data[index].image),
title: Text(snapshot.data[index].name),
subtitle: Text(snapshot.data[index].description ?? ''),
isThreeLine: true,
trailing: Padding(
padding: EdgeInsets.only(top: 8.0, right: 4.0),
child: Icon(
Icons.explore,
color: Colors.green[200],
size: 30,
),
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
OfferDetailPage(snapshot.data[index]))),
));
});
}
}
所以代码的上半部分从 ApiService.getOffers
中获取项目,然后调用 _createOfferList
来构建 Listview。
在这个方法中,itemTracker
-实例的 mobx-observable amount
被 mobx-action updateAmount(int newValue)
更新为快照数据列表的长度。
在上面的 Scaffold
中,我然后使用 Observer
来跟踪和显示项目的数量。
除了未更新的数量之外,该应用程序按预期工作并且列表得到呈现。如果我在应用程序中前后导航,列表项的数量会正确显示,但它永远不会发生在初始页面加载时。
edit:作为旁注:我没有炫耀 ItemTracker
class-定义和相应生成的 class,因为它所做的只是为 amount
-成员使用一个可观察注释,为只接受一个 int 参数并将其写入 this.amount
.[=22 的方法使用一个动作注释=]
所以今天我设法解决了我的问题,引入了一个持有物品的 class 成员,并通过在 initState()
- 中调用 itemTracker.updateAmount()
对收到物品做出反应方法。
class OfferPage extends StatefulWidget {
final Future<List<Offer>> data = ApiService.getOffers();
OfferPageState createState() => OfferPageState();
}
class OfferPageState extends State<OfferPage> {
@override
void initState() {
widget.data.then((offers) => itemTracker.updateAmount(offers.length));
super.initState();
}
// ...
//the new Scaffold body part
body: ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(20.0),
children: <Widget>[
FutureBuilder(
// no longer create a request, but instead use the existing request's future
future: widget.data,
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator(),
);
default:
return _createOfferList(context, snapshot);
}
}),
],
),
_createOfferList
-方法保持完全相同,尽管没有调用 updateAmount()
,因为这部分现在在 initState()
.
中处理
当尝试在脚手架主体内创建项目的列表视图时,我无法使用 mobx(版本:0.3.5)在另一个地方(Appbar)更新该列表中项目数量的显示和 flutter_mobx(版本:0.3.0+1)。
我已经尝试使用 Provider 包 (3.0.0+1) 解决这个问题,但这也没有解决,所以我想我遗漏了一些关于 FutureBuilder 和 Flutter 构建过程的本质.
// the mobx-store
ItemTracker itemTracker = ItemTracker();
class StartPage extends StatefulWidget {
StartPageState createState() => StartPageState();
}
class StartPageState extends State<StartPage> {
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
// this Observer doesn't update
leading: Observer(
builder: (_) => Text('Items: ' + itemTracker.amount.toString())),
title: Text('MyApp',
style: TextStyle(
color: Colors.deepPurpleAccent[50],
fontSize: 16,
fontWeight: FontWeight.bold,
)),
centerTitle: true,
),
body: ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(20.0),
children: <Widget>[
FutureBuilder(
future: ApiService.getOffers(),
builder: (BuildContext context,
AsyncSnapshot<List<Offer>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator(),
);
default:
return snapshot.hasError
? Text('Error: ${snapshot.error}')
: _createOfferList(context, snapshot);
}
}),
],
),
),
);
}
Widget _createOfferList(BuildContext context, AsyncSnapshot snapshot) {
// after receiving the response, the amount of items should get written to
// itemTracker.amount - the Observer-part should be rerendered, but it won't
itemTracker.updateAmount(snapshot.data.length);
print(snapshot.data.length.toString());
return ListView.builder(
itemCount: snapshot.data.length,
shrinkWrap: true,
primary: false,
itemBuilder: (BuildContext context, int index) {
return Card(
color: Colors.lightBlue[50],
child: ListTile(
leading: Image.asset(snapshot.data[index].image),
title: Text(snapshot.data[index].name),
subtitle: Text(snapshot.data[index].description ?? ''),
isThreeLine: true,
trailing: Padding(
padding: EdgeInsets.only(top: 8.0, right: 4.0),
child: Icon(
Icons.explore,
color: Colors.green[200],
size: 30,
),
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
OfferDetailPage(snapshot.data[index]))),
));
});
}
}
所以代码的上半部分从 ApiService.getOffers
中获取项目,然后调用 _createOfferList
来构建 Listview。
在这个方法中,itemTracker
-实例的 mobx-observable amount
被 mobx-action updateAmount(int newValue)
更新为快照数据列表的长度。
在上面的 Scaffold
中,我然后使用 Observer
来跟踪和显示项目的数量。
除了未更新的数量之外,该应用程序按预期工作并且列表得到呈现。如果我在应用程序中前后导航,列表项的数量会正确显示,但它永远不会发生在初始页面加载时。
edit:作为旁注:我没有炫耀 ItemTracker
class-定义和相应生成的 class,因为它所做的只是为 amount
-成员使用一个可观察注释,为只接受一个 int 参数并将其写入 this.amount
.[=22 的方法使用一个动作注释=]
所以今天我设法解决了我的问题,引入了一个持有物品的 class 成员,并通过在 initState()
- 中调用 itemTracker.updateAmount()
对收到物品做出反应方法。
class OfferPage extends StatefulWidget {
final Future<List<Offer>> data = ApiService.getOffers();
OfferPageState createState() => OfferPageState();
}
class OfferPageState extends State<OfferPage> {
@override
void initState() {
widget.data.then((offers) => itemTracker.updateAmount(offers.length));
super.initState();
}
// ...
//the new Scaffold body part
body: ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(20.0),
children: <Widget>[
FutureBuilder(
// no longer create a request, but instead use the existing request's future
future: widget.data,
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator(),
);
default:
return _createOfferList(context, snapshot);
}
}),
],
),
_createOfferList
-方法保持完全相同,尽管没有调用 updateAmount()
,因为这部分现在在 initState()
.