【问题标题】:Skip a tab while switching among tabs in TabBarView在 TabBarView 中切换选项卡时跳过一个选项卡
【发布时间】:2020-12-27 15:00:16
【问题描述】:

在我的 Flutter 应用中,我使用了一个简单的标签栏。我使用了来自 Flutter 网站的代码并进行了更新,以确保我可以使用 AutomaticKeepAliveClientMixin 保持每个选项卡的状态。

我有 3 个选项卡,每个选项卡都从我的后端 API 获取数据列表(为什么我需要使用 AutomaticKeepAliveClientMixin)。 问题是,当我在第一个和第三个选项卡(Page1 和 Page3)之间切换时,中间选项卡会一遍又一遍地重建,直到我切换到该选项卡(Page2),并且只有在那时它才不再重建。 每次重建都会导致从 API 获取数据,这是不可取的。 下面,我包含了一个简化的代码来重现这个问题。 一旦在第一个和第三个选项卡之间切换(不切换到第二个选项卡),您可以在调试控制台中看到它一直在打印“p2”(在我的真实应用程序中,它一直在为第二个选项卡获取数据)。

有没有一种方法可以在选项卡之间切换,而不需要在构建/重建之间切换其他选项卡?

这是我的代码。

import 'package:flutter/material.dart';

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

class TabBarDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            bottom: TabBar(
              tabs: [
                Tab(icon: Icon(Icons.directions_car)),
                Tab(icon: Icon(Icons.directions_transit)),
                Tab(icon: Icon(Icons.directions_bike)),
              ],
            ),
            title: Text('Tabs Demo'),
          ),
          body: TabBarView(
            children: [
              Page1(),
              Page2(),
              Page3(),
            ],
          ),
        ),
      ),
    );
  }
}

class Page1 extends StatefulWidget {
  @override
  _Page1State createState() => _Page1State();
}

class _Page1State extends State<Page1>
    with AutomaticKeepAliveClientMixin<Page1> {
  @override
  bool get wantKeepAlive => true;
  @override
  Widget build(BuildContext context) {
    super.build(context);
    print('p1');
    return Container(
      child: Center(
        child: Icon(Icons.directions_car),
      ),
    );
  }
}

class Page2 extends StatefulWidget {
  @override
  _Page2State createState() => _Page2State();
}

class _Page2State extends State<Page2>
    with AutomaticKeepAliveClientMixin<Page2> {
  @override
  bool get wantKeepAlive => true;
  @override
  Widget build(BuildContext context) {
    super.build(context);
    print('p2');
    return Container(
      child: Center(
        child: Icon(Icons.directions_transit),
      ),
    );
  }
}

class Page3 extends StatefulWidget {
  @override
  _Page3State createState() => _Page3State();
}

class _Page3State extends State<Page3>
    with AutomaticKeepAliveClientMixin<Page3> {
  @override
  bool get wantKeepAlive => true;
  @override
  Widget build(BuildContext context) {
    super.build(context);
    print('p3');
    return Container(
      child: Center(
        child: Icon(Icons.directions_bike),
      ),
    );
  }
}

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    我相信这不是颤振的错误,但最终归结为您的实施。 请看一下我为您编写的代码。

    import 'package:flutter/material.dart';
    import 'dart:async';
    
    class FakeApi {
      Future<List<int>> call() async {
        print('calling api');
        await Future.delayed(const Duration(seconds: 3));
        return <int>[for (var i = 0; i < 100; ++i) i];
      }
    }
    
    void main() => runApp(const MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp() : super(key: const Key('MyApp'));
    
      @override
      Widget build(BuildContext context) => const MaterialApp(home: MyHomePage());
    }
    
    class MyHomePage extends StatelessWidget {
      const MyHomePage() : super(key: const Key('MyHomePage'));
      static const _icons = [
        Icon(Icons.directions_car),
        Icon(Icons.directions_transit),
        Icon(Icons.directions_bike),
      ];
      @override
      Widget build(BuildContext context) => DefaultTabController(
            length: _icons.length,
            child: Scaffold(
              appBar: AppBar(
                bottom: TabBar(
                  tabs: [for (final icon in _icons) Tab(icon: icon)],
                ),
                title: Text('Tabs Demo'),
              ),
              body: TabBarView(
                children: [
                  Center(child: _icons[0]),
                  StaggeredWidget(_icons[1]),
                  Center(child: _icons[2]),
                ],
              ),
            ),
          );
    }
    
    class StaggeredWidget extends StatefulWidget {
      const StaggeredWidget(this.icon)
          : super(key: const ValueKey('StaggeredWidget'));
      final Icon icon;
    
      @override
      _StaggeredWidgetState createState() => _StaggeredWidgetState();
    }
    
    class _StaggeredWidgetState extends State<StaggeredWidget> {
      Widget _child;
    
      Timer _timer;
    
      @override
      void initState() {
        super.initState();
        _timer = Timer(const Duration(milliseconds: 150), () {
          if (mounted) {
            setState(() => _child = MyApiWidget(widget.icon));
          }
        });
      }
    
      @override
      void dispose() {
        _timer.cancel();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) => _child ?? widget.icon;
    }
    
    class MyApiWidget extends StatefulWidget {
      const MyApiWidget(this.icon, [Key key]) : super(key: key);
      final Icon icon;
      @override
      _MyApiWidgetState createState() => _MyApiWidgetState();
    }
    
    class _MyApiWidgetState extends State<MyApiWidget>
        with AutomaticKeepAliveClientMixin {
      final _api = FakeApi();
      @override
      Widget build(BuildContext context) {
        print('building `MyApiWidget`');
        super.build(context);
        return FutureBuilder<List<int>>(
          future: _api(),
          builder: (context, snapshot) => !snapshot.hasData
              ? const Center(child: CircularProgressIndicator())
              : snapshot.hasError
                  ? const Center(child: Icon(Icons.error))
                  : ListView.builder(
                      itemBuilder: (context, index) => ListTile(
                        title: Text('item $index'),
                      ),
                    ),
        );
      }
    
      @override
      bool get wantKeepAlive => true;
    }
    

    【讨论】:

      猜你喜欢
      • 2018-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-21
      • 1970-01-01
      • 1970-01-01
      • 2011-11-21
      相关资源
      最近更新 更多