颤振:在抽屉中更改主体时保留状态

时间:2019-05-09 11:55:14

标签: flutter navigation drawer

我正在使用材质库的Drawer类创建带有导航抽屉的Flutter应用程序。包含Widget的{​​{1}}是Drawer,并且StatefulWidget的内容根据导航抽屉上的选定项目显示。内容为ScaffoldWidgetOne,两者都保持自己的状态为WidgetTwo。请参见下面的代码示例。

此刻,当我从一个小部件更改为另一个小部件并返回时,先前显示的小部件的整个状态将重新加载。这是不理想的,因为两个小部件都通过API进行了网络调用,因此需要相应地重新绘制。

到目前为止我尝试过的一切

代码

IndexedStack

所需结果

class DrawerWidget extends StatefulWidget { @override State<StatefulWidget> createState() => _DrawerState(); } class _DrawerState extends State<DrawerWidget> { Widget _activeWidget; @override void initState() { _activeWidget = FirstWidget(); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("Drawer demo")), drawer: Drawer( child: ListView( padding: EdgeInsets.zero, children: <Widget>[ ListTile( title: Text("First Widget"), onTap: () { setState(() { _activeWidget = FirstWidget(); }); }, ), ListTile( title: Text("Second Widget"), onTap: () { setState(() { _activeWidget = SecondWidget(); }); }, ), ], ), ), body: _activeWidget); } } class FirstWidget extends StatefulWidget { // [..] } class SecondWidget extends StatefulWidget { // [..] } WidgetOne仅在初始加载时加载(在WidgetTwo中选择它们后)。如果先前已加载过该小部件,则切换回另一个小部件不应重新加载该小部件。子窗口小部件不应仅在初次按下时直接全部加载。

实际结果

每次在Drawer中被选中时,FirstWidgetSecondWidget都被重新加载和重绘。

1 个答案:

答案 0 :(得分:0)

我通过使用PageView并在所有子窗口小部件上实现了AutomaticKeepAliveClientMixin解决了这个问题:

class DrawerWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _DrawerState();
}

class _DrawerState extends State<DrawerWidget> {
  final _pageController = PageController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("Drawer demo")),
        drawer: Drawer(
          child: ListView(
            padding: EdgeInsets.zero,
            children: <Widget>[
              ListTile(
                title: Text("First Widget"),
                onTap: () {
                  _pageController.jumpToPage(0);
                },
              ),
              ListTile(
                title: Text("Second Widget"),
                onTap: () {
                  _pageController.jumpToPage(1);
                },
              ),
            ],
          ),
        ),
        body: PageView(
          controller: _pageController,
          children: <Widget>[
            FirstWidget(),
            SecondWidget()
          ],
          physics: NeverScrollableScrollPhysics()
        ));
  }
}

class FirstWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _FirstWidgetState();
}

class _FirstWidgetState extends State<FirstWidget> with AutomaticKeepAliveClientMixin<FirstWidget> {
  // [..]

  @override
  bool get wantKeepAlive => true;
} 

class SecondWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _SecondWidgetState();
}

class _SecondWidgetState extends State<SecondWidget> with AutomaticKeepAliveClientMixin<SecondWidget> {
  // [..]

  @override
  bool get wantKeepAlive => true;
}

现在,所有小部件仅在初次切换时才在导航抽屉中加载,而在切换回时不会重新加载。