Flutter有状态小部件会重新创建状态。

7
我正在开发一个Flutter应用程序,发现了一些与状态管理相关的意外行为。我创建了一个示例应用程序来重现这种行为,你可以在以下找到代码和日志输出。
该应用程序包含一个简单的ListView,其中包含10个有状态的Container(Text+Decoration)。当我向下滚动时,每个容器及其容器状态将像预期的那样被创建一次。当我再次向上滚动时,Flutter会为每个再次出现在显示屏上的容器小部件重新创建所有状态(但不是容器小部件本身)。我希望Flutter能够检索先前的状态而不必重新创建整个状态对象。请问我这里做错了什么吗?
样例代码请参考以下链接:Sample App
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key) {
    print("MyHomePage constructor");
  }

  @override
  _MyHomePageState createState() {
    print("createState");
    return _MyHomePageState();
  }
}

class _MyHomePageState extends State<MyHomePage> {
  _MyHomePageState() {
    print("_MyHomePageState contructor");
  }

  void initState() {
    super.initState();

    print("_MyHomePageState initState");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: ListView.builder(
          itemBuilder: (context, index) {
            return ContainerWidget(index, key: ValueKey(index));
          },
          itemCount: 10,
        ));
  }
}

class ContainerWidget extends StatefulWidget {
  int index;

  ContainerWidget(this.index, {key}) : super(key: key) {
    print("ContainerWidget constructor for index $index");
  }

  @override
  State<StatefulWidget> createState() {
    print("ContainerWidget createState for index $index");
    return _ContainerState();
  }
}

class _ContainerState extends State<ContainerWidget> {
  _ContainerState() {
    print("_ContainerState constructor");
  }

  void initState() {
    super.initState();

    print("_ContainerState initState for index ${widget.index}");
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: Text("Index: ${widget.index}"),
      ),
      height: 200,
      decoration: BoxDecoration(
        border: Border(
          bottom: BorderSide(color: Colors.green),
        ),
      ),
    );
  }
}


日志输出:

I/flutter (22400): createState
I/flutter (22400): _MyHomePageState contructor
I/flutter (22400): _MyHomePageState initState
I/flutter (22400): ContainerWidget constructor for index 0
I/flutter (22400): ContainerWidget createState for index 0
I/flutter (22400): _ContainerState constructor
I/flutter (22400): _ContainerState initState for index 0
I/flutter (22400): ContainerWidget constructor for index 1
I/flutter (22400): ContainerWidget createState for index 1
I/flutter (22400): _ContainerState constructor
I/flutter (22400): _ContainerState initState for index 1
I/flutter (22400): ContainerWidget constructor for index 2
I/flutter (22400): ContainerWidget createState for index 2
I/flutter (22400): _ContainerState constructor
I/flutter (22400): _ContainerState initState for index 2
I/flutter (22400): ContainerWidget constructor for index 3
I/flutter (22400): ContainerWidget createState for index 3
I/flutter (22400): _ContainerState constructor
I/flutter (22400): _ContainerState initState for index 3
I/flutter (22400): ContainerWidget constructor for index 4
I/flutter (22400): ContainerWidget createState for index 4
I/flutter (22400): _ContainerState constructor
I/flutter (22400): _ContainerState initState for index 4
I/flutter (22400): ContainerWidget constructor for index 5
I/flutter (22400): ContainerWidget createState for index 5
I/flutter (22400): _ContainerState constructor
I/flutter (22400): _ContainerState initState for index 5
I/flutter (22400): ContainerWidget createState for index 1
I/flutter (22400): _ContainerState constructor
I/flutter (22400): _ContainerState initState for index 1
I/flutter (22400): ContainerWidget createState for index 0
I/flutter (22400): _ContainerState constructor
I/flutter (22400): _ContainerState initState for index 0
1个回答

7
这很正常,因为当项目离开屏幕时,它们会被卸载。
如果您不想这样,请使用我们所称的“保持活动”功能。您可以通过向 State 类中添加一个mixin 来实现:
class _MyHomePageState extends State<MyHomePage> with AutomaticKeepAliveClientMixin {

  bool get wantKeepAlive => true;


  // ...
 }

假设我想开发一个带有n个容器的中心页面。每个容器处理各种复杂度的任务,例如从远程获取和处理数据。在您看来,是将AutomaticKeepAliveClientMixin添加到每个容器中最好的解决方案,还是像包含n个容器的SingleChildScrollView这样的东西?我想防止在滚动时反复调用任务。 - 0xPixelfrost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接