dart - Flutter 切换到 Tab 重新加载小部件并运行 FutureBuilder

问题:

我有 2 个使用默认选项卡 Controller 的选项卡,如下所示:

Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        drawer: Menu(),
        appBar: AppBar(
          title: Container(
            child: Text('Dashboard'),
          ),
          bottom: TabBar(
            tabs: <Widget>[
              Container(
                padding: EdgeInsets.all(8.0),
                child: Text('Deals'),
              ),
              Container(
                padding: EdgeInsets.all(8.0),
                child: Text('Viewer'),
              ),
            ],
          ),
        ),
        body: TabBarView(
          children: <Widget>[
            DealList(),
            ViewersPage(),
          ],
        ),
      ),
    );
  }
}

DealList() 是一个 StatefulWidget,它是这样构建的:

Widget build(BuildContext context) {
    return FutureBuilder(
      future: this.loadDeals(),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        print('Has error: ${snapshot.hasError}');
        print('Has data: ${snapshot.hasData}');
        print('Snapshot data: ${snapshot.data}');
        return snapshot.connectionState == ConnectionState.done
            ? RefreshIndicator(
                onRefresh: showSomething,
                child: ListView.builder(
                  physics: const AlwaysScrollableScrollPhysics(),
                  itemCount: snapshot.data['deals'].length,
                  itemBuilder: (context, index) {
                    final Map deal = snapshot.data['deals'][index];
                    print('A Deal: ${deal}');
                    return _getDealItem(deal, context);
                  },
                ),
              )
            : Center(
                child: CircularProgressIndicator(),
              );
      },
    );
  }
}

有了上述内容,当我切换回 DealList() 选项卡时,会发生以下情况:它会重新加载。

有没有办法防止 FutureBuilder 在完成一次后重新运行? (计划是让用户使用 RefreshIndicator 重新加载。因此,除非用户明确这样做,否则更改选项卡不应触发任何事情。)

最佳答案

这里有两个问题,第一个:

TabController 切换选项卡时,它会卸载旧的小部件树以节省内存。如果你想改变这种行为,你需要混入 AutomaticKeepAliveClientMixin到您的标签小部件的状态。

class _DealListState extends State<DealList> with AutomaticKeepAliveClientMixin<DealList> {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    super.build(context); // need to call super method.
    return /* ... */
  }
}

第二个问题是您使用 FutureBuilder - 如果你给一个FutureBuilder提供一个新的Future,它无法判断结果会和上次一样,所以它必须重建。 (请记住,Flutter 可能每帧最多调用一次构建方法)。

return FutureBuilder(
  future: this.loadDeals(), // Creates a new future on every build invocation.
  /* ... */
);

相反,您希望在 initState 中将 future 分配给 State 类的成员,然后将此值传递给 FutureBuilder。这确保了后续重建的 future 是相同的。如果您想强制 State 重新加载交易,您始终可以创建一个重新分配 _loadingDeals 成员并调用 setState 的方法。

Future<...> _loadingDeals;

@override
void initState() {
  _loadingDeals = loadDeals(); // only create the future once.
  super.initState();
}

@override
Widget build(BuildContext context) {
  super.build(context); // because we use the keep alive mixin.
  return new FutureBuilder(future: _loadingDeals, /* ... */);
}

https://stackoverflow.com/questions/51224420/

相关文章:

android-studio - Dart 的 SDK 在/flutter 文件夹中的什么位置?

android-studio - 带有 Flutter 更新的 Android Studio 导致了

flutter - 创建一个带有圆形边框的按钮

flutter - 如何将 BottomNavigationBar 与 Navigator 一起使用

flutter - 如何更改文本字段 flutter 中的值?

dart - 如何在另一个 flutter 应用程序中使用本地 flutter 包?

dart - 使用不包含 MediaQuery 的上下文调用的 Flutter 错误 : Media

Flutter - 如何将用户数据传递给所有 View

flutter - 如何确定屏幕高度和宽度

flutter - 弹出时强制 Flutter 导航器重新加载状态