状态更改后,如何强制立即重绘FutureBuilder?

时间:2018-06-22 03:47:08

标签: flutter

当我更改特定的futurebuilder小部件所依赖的状态时,直到异步任务完成后才重绘该小部件。我希望状态更改后立即重绘该小部件。以下是futurebuilder的代码:

child: new FutureBuilder(
            future: _api.getListOfTourneys(searchTerm, filterChecks, pageNum),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                if(!(snapshot.data is List)){
                  return new TourneyItem(snapshot.data['tournament']);
                }
                return new Expanded(
                    child: ListView.builder(
                  shrinkWrap: false,
                  scrollDirection: Axis.vertical,
                  itemCount: snapshot.data.length,
                  itemBuilder: (BuildContext context, int index) {
                    return TourneyItem(snapshot.data[index]);
                  },
                ));
              } else if (snapshot.hasError) {
                return new Text("No results found");
              } else {
                return new CircularProgressIndicator();
              }
            },
          )

3 个答案:

答案 0 :(得分:2)

我认为FutureBuilder在启动时只构建一次,然后每次执行异步任务时都会构建。 因此,当我们导航至屏幕FutureBuilder是在开始时构建的,然后在异步任务完成时,则对于其他调用(首先除外),FutureBuilder仅在异步任务完成后构建。

我还需要在异步调用开始时重建FutureBuilder,我使用snapshot.connectionState

解决了此问题

FutureBuilder的内部构建器

if(snapshot.connectionState == ConnectionState.done){
    if(snapshot.hasData){
        //Show data here
    }else{
       //Show error here
    }
}else{
    //Show progress
}

答案 1 :(得分:2)

您不能使用FutureBuilder做到这一点。如果您要构建的不仅仅是“初始” +“完成”,请不要使用FutureBuilder。

相反,您可以通过将将来的结果提交到流中来使用StreamStreamBuilder

class Foo extends StatefulWidget {
  @override
  _FooState createState() => _FooState();
}

class _FooState extends State<Foo> {
  StreamController streamController;

  @override
  void initState() {
    load();
    super.initState();
  }

  load() async {
    streamController.add("Loading");
    await Future.delayed(Duration(seconds: 1));
    streamController.add("Done");
  }

  @override
  void didUpdateWidget(Foo oldWidget) {
    if (somethingChanged) {
      load();
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
    void dispose() {
      streamController.close();
      super.dispose();
    }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<String>(
      stream: streamController.stream,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return new Text(snapshot.data);
        } else if (snapshot.hasError) {
          return new Text("Error");
        } else {
          return new Text("Nothing");
        }
      },
    );
  }
}

答案 2 :(得分:-1)

这有点晚了,但它对我有用,只需用相同的屏幕替换屏幕

Navigator.pushReplacement(context,
    MaterialPageRoute(
        builder: (BuildContext context) =>
           *SamePage*()
    )
);

不要在 showdialog 中使用此方法以避免在同一页面上返回两次!