【问题标题】:Flutter: preserve state when changing body in DrawerFlutter:在 Drawer 中更改 body 时保留状态
【发布时间】:2019-09-27 06:11:51
【问题描述】:

我正在使用 Material 库的 Drawer 类创建一个带有导航抽屉的 Flutter 应用程序。包含DrawerWidgetStatefulWidgetScaffold 的内容根据导航抽屉上的选定项显示。内容是WidgetOneWidgetTwo,两者都保持自己的状态为StatefulWidgets。请参阅下面的代码示例。

目前,当我从一个小部件切换到另一个小部件并返回时,之前显示的小部件的整个状态都会重新加载。这并不理想,因为这两个小部件都有来自 API 的网络调用,并且需要相应地重绘。

到目前为止我已经尝试过什么

代码

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 {
  // [..]
}

想要的结果

WidgetOneWidgetTwo 仅在初始加载时加载(在 Drawer 中选择它们之后)。如果之前已经加载过,则切换到另一个小部件并返回不应重新加载小部件。子小部件不应全部直接加载,只有在它们最初被按下时才加载。

实际结果

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

【问题讨论】:

  • 您需要一个 PageView 或类似的东西,KeepAlive 才能工作。

标签: flutter navigation drawer


【解决方案1】:

我通过使用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;
}

现在,所有小部件仅在导航抽屉中的初始切换时加载,并且在切换回时不会重新加载。

【讨论】:

    猜你喜欢
    • 2021-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-13
    • 1970-01-01
    • 1970-01-01
    • 2021-09-10
    • 2019-10-06
    相关资源
    最近更新 更多