使用FutureBuilder时,Mobx Observer无法正常工作

时间:2019-08-09 15:36:52

标签: flutter dart mobx

当尝试在脚手架体内创建项目的Listview时,我无法使用mobx(版本:0.3.5)和flutter_mobx更新该列表在另一个位置(Appbar)中项目数量的显示(版本:0.3.0 + 1)。

我已经尝试使用Provider软件包(3.0.0 + 1)来解决此问题,但这还没有解决,所以我想我缺少有关FutureBuilder和Flutter构建过程本质的信息。 / p>

// 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可观察的amount由mobx动作updateAmount(int newValue)使用快照的数据列表的长度进行更新。
然后,在上面的Scaffold中,我使用Observer来跟踪和显示项目数量。
除了未更新的金额外,该应用程序还可以按预期工作,并且列表已呈现。如果我在该应用程序中来回导航,则可以正确显示列表项的数量,但是在初始页面加载中却永远不会发生。

edit :只是一个旁注:我没有展示ItemTracker类定义和相应的生成类,因为它所做的只是使用可观察的注释amount成员,并为该方法的动作注释添加一个int参数并将其写入this.amount

1 个答案:

答案 0 :(得分:0)

因此,今天我设法通过引入持有项目的类成员来实现针对我的问题的解决方法,并通过在itemTracker.updateAmount()方法内调用initState()来响应接收它们。

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()内部处理。