TabBarView 内的 Flutter Futurebuilder 在选项卡之间切换时初始应用程序加载后不会触发未来?

Flutter Futurebuilder inside TabBarView not triggering the future after initial application load while switching between tabs?

我是 flutter 的新手,正在尝试在 flutter 应用程序的主页中实现一个 tabview。

第一个选项卡是从 firebase 远程配置的数据填充的,第二个选项卡是使用 Futurebuilder 填充的。当我切换选项卡时,未来功能不会触发。它仅在初始应用程序加载期间触发。每当我切换标签并返回到第二个标签时。 futurebuilder的future函数不再触发

有人可以为此提供任何解决方案吗?

Container(
                  width: MediaQuery.of(context).size.width,
                  color: Colors.white,
                  child: GridView.count(
                    shrinkWrap: true,
                    physics: BouncingScrollPhysics(),
                    padding: const EdgeInsets.all(4.0),
                    childAspectRatio: 1.0,
                    crossAxisCount: isTablet ? 2 : 1,
                    crossAxisSpacing: 4.0,
                    mainAxisSpacing: 4.0,
                    children: [
                      FutureBuilder(
                          future: _getBookmarks,
                          builder:
                              (BuildContext context, AsyncSnapshot snapshot) {
                            var listWidget;
                            if (snapshot.connectionState ==
                                ConnectionState.done) {
                              if (snapshot.data.length == 0) {
                                listWidget = Container(
                                    child: Center(
                                  child: Text("No Favorites to Display!"),
                                ));
                              } else {
                                listWidget = ListView.builder(
                                  itemCount: snapshot.data.length,
                                  itemBuilder: (context, index) {
                                    final bookmarks = snapshot.data[index];
                                    return BuildFavoriteCard(
                                        bookmarks, context);
                                  },
                                );
                              }
                            } else {
                              listWidget = Center(
                                child: CircularProgressIndicator(),
                              );
                            }
                            return listWidget;
                          })
                    ],
                  ))

这里是结合 Flutter 文档的 TabBar 和 FutureBuilder 示例的示例。

如果你 运行 这样做,你会看到每次导航到第一个选项卡时都会创建一个新的未来(因为重建了 TabBarView 的内容)。

我假设这目前对你不起作用,因为你的未来 _getBookmarks 被定义在小部件树中更高的地方(在不通过切换选项卡重建的部分)。

解决方案是将未来移动到您的 TabBarView 小部件中。

import 'package:flutter/material.dart';

void main() {
  runApp(const TabBarDemo());
}

class TabBarDemo extends StatelessWidget {
  const TabBarDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 2,
        child: Scaffold(
          appBar: AppBar(
            bottom: const TabBar(
              tabs: [
                Tab(icon: Icon(Icons.directions_car)),
                Tab(icon: Icon(Icons.directions_transit)),
              ],
            ),
            title: const Text('Tabs Demo'),
          ),
          body: TabBarView(
            children: [
              Center(
                child: MyStatefulWidget(),
              ),
              Icon(Icons.directions_transit),
            ],
          ),
        ),
      ),
    );
  }
}

/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({
    Key? key,
  }) : super(key: key);

  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

/// This is the private State class that goes with MyStatefulWidget.
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  Future<String>? _calculation;

  @override
  void initState() {
    _calculation = Future<String>.delayed(
      const Duration(seconds: 2),
      () => 'Data Loaded',
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTextStyle(
      style: Theme.of(context).textTheme.headline2!,
      textAlign: TextAlign.center,
      child: FutureBuilder<String>(
        future:
            _calculation, // calculation, // a previously-obtained Future<String> or null
        builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
          List<Widget> children;
          if (snapshot.hasData) {
            children = <Widget>[
              const Icon(
                Icons.check_circle_outline,
                color: Colors.green,
                size: 60,
              ),
              Padding(
                padding: const EdgeInsets.only(top: 16),
                child: Text('Result: ${snapshot.data}'),
              ),
            ];
          } else if (snapshot.hasError) {
            children = <Widget>[
              const Icon(
                Icons.error_outline,
                color: Colors.red,
                size: 60,
              ),
              Padding(
                padding: const EdgeInsets.only(top: 16),
                child: Text('Error: ${snapshot.error}'),
              )
            ];
          } else {
            children = const <Widget>[
              SizedBox(
                child: CircularProgressIndicator(),
                width: 60,
                height: 60,
              ),
              Padding(
                padding: EdgeInsets.only(top: 16),
                child: Text('Awaiting result...'),
              )
            ];
          }
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: children,
            ),
          );
        },
      ),
    );
  }
}