8
6

More than 3 years have passed since last update.

Flutter TabBarView + ListViewのステート保存パターン

Posted at

はじめに

Tab + ListViewの画面構成時に Widget の状態 (State) を保存する方法をまとめておきます。
Screenshot_1582990818.png

[方法その1] PageStorageKeyを利用

Widget のKeyPageStorageKeyのインスタンスを指定するだけです。PageStorageKey自体についての解説はこちらを参照してください。

サンプルコード
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
          bottom: TabBar(
            tabs: <Widget>[
              Tab(
                child: Text('Tab-1'),
              ),
              Tab(
                child: Text('Tab-2'),
              ),
            ],
          ),
        ),
        body:
        TabBarView(
          children: <Widget>[
            // Stateが保存されないパターン
            //_TabPage(tab: 0),
            //_TabPage(tab: 1),

            // PageStorageKeyを利用してStateを保存するパターン
            _TabPage(key: PageStorageKey(0), tab: 0),
            _TabPage(key: PageStorageKey(1), tab: 1),
          ],
        ),
      ),
    );
  }
}

class _TabPage extends StatefulWidget {
  _TabPage({Key key, this.tab}) : super(key: key);

  final int tab;

  @override
  _TabPageState createState() => _TabPageState();
}

class _TabPageState extends State<_TabPage> {
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: 100,
      itemBuilder: (BuildContext context, int index) {
        return ListTile(
          title:
            Text('${widget.tab}: Item $index'),
        );
      },
    );
  }
}

[方法その2] AutomaticKeepAliveClientMixinを利用

PageStorageKeyを使わず、Stateインスタンスに対してAutomaticKeepAliveClientMixinをMix-inすることでもいけます。

ソースコードはこちら

編集箇所
class _TabPageState extends State<_TabPage> with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true; // 追加!

  @override
  Widget build(BuildContext context) {
    super.build(context); // 追加!
サンプルコード
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
          bottom: TabBar(
            tabs: <Widget>[
              Tab(
                child: Text('Tab-1'),
              ),
              Tab(
                child: Text('Tab-2'),
              ),
            ],
          ),
        ),
        body:
        TabBarView(
          children: <Widget>[
            // AutomaticKeepAliveClientMixinを利用してStateを保存するパターン
            _TabPage(tab: 0),
            _TabPage(tab: 1),
          ],
        ),
      ),
    );
  }
}

class _TabPage extends StatefulWidget {
  _TabPage({Key key, this.tab}) : super(key: key);

  final int tab;

  @override
  _TabPageState createState() => _TabPageState();
}

class _TabPageState extends State<_TabPage> with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true; // 追加!

  @override
  Widget build(BuildContext context) {
    super.build(context); // 追加!

    return ListView.builder(
      itemCount: 100,
      itemBuilder: (BuildContext context, int index) {
        return ListTile(
          title:
            Text('${widget.tab}: Item $index'),
        );
      },
    );
  }
}
8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6