【问题标题】:Why does adding a stateful widget to the end of the list of TabItems call initState and dispose?为什么将有状态小部件添加到 TabItems 列表的末尾会调用 initState 和 dispose?
【发布时间】:2021-12-03 07:15:18
【问题描述】:

我有一个 defaultTabController,它根据 TabItem(title, widget) 列表显示选项卡和 TabBarView,其中标题是选项卡中的标题,小部件是显示在 TabBarView 中的有状态小部件。

每当我widgetList.add() 一个新的TabItem 到这个TabItem 列表时,就会调用该有状态小部件的initState() 和dispose()。但是当我 widgetList.insert 它没有。

只是好奇为什么只有在将它添加到列表末尾时才会发生这种情况。

这是一个展示这一点的 DartPad。在尝试使用 widgetList.add 和 widgetList.insert 时,只需相应地评论和取消评论: https://dartpad.dev/?id=d84d7236a50c0c4769427fcc8b287f41&null_safety=true

谢谢!

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    我观察到考虑不同的 scnarios。

    1. widgetList 为空,正在使用 add
    List<TabItem> widgetList = [];
    ..
    // added this count to check which widget is calling init or dispose
    widgetList.add(TabItem("Added", AWidget(count: count)));
    
    • 初始:无小部件
    • 第一次按下:添加小部件(打印 init 0)
    • 第二次按下:添加另一个小部件(打印 init1 dispose1)
    • 进一步印刷:不打印任何东西
    1. widgetList 包含 3 个选项卡并使用添加
    List<TabItem> widgetList = [];
    ..
    // added this count to check which widget is calling init or dispose
    List<TabItem> widgetList = [
        TabItem("Test", const AWidget(count: 0)),
        TabItem("Test", const AWidget(count: 1)),
        TabItem("Test", const AWidget(count: 2))
      ];
    
    • 初始:包含 2 个选项卡(打印 init0)
    • 进一步印刷:不打印任何东西
    1. widgetList 为空,正在使用插入
    List<TabItem> widgetList = [];
    ..
    // added this count to check which widget is calling init or dispose
    widgetList.insert(count, TabItem("Added", AWidget(count: count)));
    
    • 初始:无小部件
    • 第一次按下:添加小部件(打印 init 0)
    • 第二次按下:添加另一个小部件(打印 init1 dispose1)
    • 进一步印刷:不打印任何东西
    1. widgetList 包含 3 个选项卡并使用插入功能
    List<TabItem> widgetList = [
        TabItem("Test", const AWidget(count: 0)),
        TabItem("Test", const AWidget(count: 1)),
        TabItem("Test", const AWidget(count: 2))
      ];
    ..
    // added this count to check which widget is calling init or dispose
    widgetList.insert(count, TabItem("Added", AWidget(count: count)));
    
    • 初始:包含 2 个选项卡(打印 init0)
    • 进一步印刷:不打印任何东西

    考虑所有 4 种情况:您只获得一次 init 和 dispose,即当只有 1 个选项卡并且您正在添加第 2 个选项卡时。这是因为添加的选项卡在添加到TabBar 时会初始化并立即释放。

    我假设标签栏在添加第二个标签时初始化(预期的)功能,然后在添加其余标签时正常工作。

    通常是两个或多个 Tab 小部件的列表。

    我的假设是基于here 的这句话。

    我可以肯定地说,这种行为是由 TabBar 而不是 List 引起的。

    add 和 insert 工作方式相似,对这种行为没有任何影响。

    同时,当您切换到其他选项卡时,假设是从 0->1。然后打印,init1,dispose0。这是因为当离开小部件时,它会初始化新的小部件并处理以前使用的小部件(就像导航活动一样)。

    我还想指出一件事。考虑使用add 而不是insert,除非由于时间复杂性需要。

    我用来测试的完整代码(包括计数):

    import 'package:flutter/material.dart';
    
    class TabItem {
      final String title;
      final Widget widget;
    
      TabItem(this.title, this.widget);
    }
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({
        Key? key,
      }) : super(key: key);
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      List<TabItem> widgetList = [];
      int _count = 0; // use 3 when using below commented code
      
    //   List<TabItem> widgetList = [
    //     TabItem("Test", const AWidget(count: 0)),
    //     TabItem("Test", const AWidget(count: 1)),
    //     TabItem("Test", const AWidget(count: 2))
    //   ];
    
      void _incrementCounter(int count) {
        setState(() {
          widgetList.add(TabItem("Added", AWidget(count: count)));
    //       widgetList.insert(count, TabItem("Added", AWidget(count: count)));
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('Main Page'),
          ),
          body: DefaultTabController(
            length: widgetList.length,
            child: Builder(
              builder: (BuildContext context) {
                return Scaffold(
                  appBar: AppBar(
                    title: const Text("Press floating button to add to list"),
                    bottom: TabBar(
                      isScrollable: true,
                      tabs: <Tab>[
                        for (var i in widgetList)
                          Tab(
                            text: i.title,
                          )
                      ],
                    ),
                  ),
                  body: TabBarView(
                      children: [for (var i in widgetList) i.widget]),
                );
              },
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              _incrementCounter(_count++);
            },
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ),
        );
      }
    }
    
    class AWidget extends StatefulWidget {
      const AWidget({
        Key? key,
        this.count=0,
      }) : super(key: key);
      
      final int count;
    
      @override
      _AWidgetState createState() => _AWidgetState();
    }
    
    class _AWidgetState extends State<AWidget> {
      @override
      void initState() {
        super.initState();
        print('initState ${widget.count}');
      }
    
      @override
      void dispose() {
        print('dispose ${widget.count}');
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Text('something ${widget.count}');
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-10
      • 1970-01-01
      • 2021-08-16
      • 2021-06-05
      • 1970-01-01
      • 2016-04-13
      • 2018-02-06
      相关资源
      最近更新 更多