Flutter:当父母的状态改变时,子小部件的状态会丢失

时间:2021-03-31 11:30:29

标签: flutter flutter-state

我正在学习 Flutter 并且正在努力解决一些状态管理问题。

我有一个 HomeScreen 小部件,其中包含 Scaffold 和一个 BottomNavigationBar。要根据BottomNavigationBar 中选定的选项卡切换页面,我将PageView 与PageController 一起使用。以下是 HomeScreen 小部件的 build 方法的外观:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: _currentIndex == 2,
      appBar: AppBar(...properties),
      body: PageView(
        controller: _pageController,
        children: _pages,
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[...items],
        currentIndex: _currentIndex,
        onTap: _onItemTapped,  //This changes state _currentIndex and calls the method _pageController.jumpToPage(_currentIndex);
      ),
    );
  }
  • _currentIndex 最初为 0。
  • _pages 是一个包含 3 个小部件的列表。
  • _pageController 是一个简单的 PageController,initialPage 设置为 0。

如果您注意到我正在使用使用 extendBodyBehindAppBar: _currentIndex == 2 状态的属性 _currentIndex,这会导致问题。 当我点击 BottomNavigationBar 上的最后一个 Tab 时,状态 _currentIndex 更改为 2,因此 extendBodyBehindAppBar 设置为 true,这使得整个 Scaffold 重建自身,PageView 的状态为丢失了。

如果注释掉 extendBodyBehindAppBar: _currentIndex == 2 行,那么即使 Scaffold 重建了 PageView 小部件的状态。

据我所知,即使父级重建,Flutter 也应该保持子级 Widgets 的状态,因为 WidgetTree 没有改变或重新排列。我尝试在 PageView 上使用 Key 但没有任何效果。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

参考Lucas Salton Cardinali post on medium 你需要使用PageStorage来持久化你需要的child被销毁后的状态。

这里是从同一页面检索的示例:

import 'package:flutter/material.dart';

// ...

void main() => runApp(MyApp());

// ...

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final List<Widget> pages = <Widget>[
    ColorBoxPage(
      key: PageStorageKey('pageOne'),
    ),
    ColorBoxPage(
      key: PageStorageKey('pageTwo'),
    )
  ];
  int currentTab = 0;
  final PageStorageBucket _bucket = PageStorageBucket();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Persistence Example"),
      ),
      body: PageStorage(
        child: pages[currentTab],
        bucket: _bucket,
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: currentTab,
        onTap: (int index) {
          setState(() {
            currentTab = index;
          });
        },
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'page 1',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.settings),
            label: 'page2',
          ),
        ],
      ),
    );
  }
}

class ColorBoxPage extends StatelessWidget {
  ColorBoxPage({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemExtent: 250.0,
      itemBuilder: (context, index) => Container(
        padding: EdgeInsets.all(10.0),
        child: Material(
          color: index % 2 == 0 ? Colors.cyan : Colors.deepOrange,
          child: Center(
            child: Text(index.toString()),
          ),
        ),
      ),
    );
  }
}