首页 > 解决方案 > 何时在 Flutter 中使用 FutureBuilder

问题描述

我想知道什么时候使用 FutureBuilder 以及它是如何有用的,因为一个小部件可以在其生命周期内多次构建,而不仅仅是在我们 setState 或更新它时,所以不要使用下面的代码:

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool done = false;

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

  Future<void> wait() async {
    await Future.delayed(Duration(seconds: 2));
    setState(() {
      done = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    print('is built');
    return done ? Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    ) : Scaffold(body: CircularProgressIndicator(),);
  }
}

在哪些情况下,FutureBuilder 会为我工作,而不是上面的设置,因为我还想优化我的应用程序以减少后端读取(在 FutureBuilder 中我会读取不止一次)。我正在寻找 FutureBuilder 比上述设置更有用和更正确的情况。

标签: flutteroptimizationfuture

解决方案


FutureBuilder用于处理返回要显示的数据的“异步”调用。

例如,假设我们必须List<String>从服务器获取 a。

API调用:

  Future<List<String>> getStringList() async {
    try {
      return Future.delayed(Duration(seconds: 1)).then(
        (value) => ['data1', 'data2', 'data3', 'data4'],
      );
    } catch (e) {
      throw Exception(e);
    }
  }

我们如何使用以下方法处理上述 API 调用状态(加载、数据、错误...等)FutureBuilder

FutureBuilder<List<String>?>(
        future: getStringList(),
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
              return Center(
                child: CircularProgressIndicator(),
              );
            case ConnectionState.done:
              if (snapshot.hasError)
                return Text(snapshot.error.toString());
              else
                return ListView(
                  children: snapshot.data!.map((e) => Text(e)).toList(),
                );

            default:
              return Text('Unhandle State');
          }
        },
      ),

正如我们所看到的,我们不必创建一个带有变量isLoading boolString错误的状态类......等等。FutureBuilder节省我们的时间。

由于FutureBuilder是一个小部件并且存在于小部件树中,因此重建可以FutureBuilder再次运行。

所以我会说你可以FutureBuilder在你知道不会重建时使用,但是有很多方法(在互联网上)可以防止FutureBuilder在重建发生时再次被调用,但它对我不起作用并导致意外行为。

老实说,我更喜欢使用任何状态管理解决方案来处理不同类中的状态,而不是使用FutureBuilder它,因为它会更安全(重建不会影响它)、更有用且更易于阅读(从 UI 中扩展业务逻辑)。


推荐阅读