Flutter タブに切り替えるとウィジェットが再読み込みされ、FutureBuilder が実行されます 質問する

Flutter タブに切り替えるとウィジェットが再読み込みされ、FutureBuilder が実行されます 質問する

問題:

次のように、Default Tabs Controller を使用するタブが 2 つあります。

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 を使用してリロードします。したがって、ユーザーが明示的に変更しない限り、タブを変更しても何もトリガーされません。)

ベストアンサー1

ここでは 2 つの問題があります。1 つ目は次のとおりです。

タブを切り替えると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 /* ... */
  }
}

2 番目の問題は、 の使用方法にあります。にFutureBuilder新しい を提供すると、結果が前回と同じになるかどうかがわからないため、再構築する必要があります。(Flutter はフレームごとに最大 1 回、ビルド メソッドを呼び出す場合があることに注意してください)。FutureFutureBuilder

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

代わりに、initState で State クラスのメンバーに future を割り当て、この値を に渡します。 は、後続の再構築で future が同じになることを保証します。 State に取引を強制的に再ロードさせたい場合は、いつでもメンバーを再割り当てして を呼び出すFutureBuilderメソッドを作成できます。_loadingDealssetState

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, /* ... */);
}

おすすめ記事