在 flutter 中强制重建有状态子部件

Dam*_*ien 13 stateful dart flutter

假设我有一个主屏幕(有状态小部件),其中有一个变量count作为状态。在此主屏幕中,有一个按钮和另一个有状态小部件(我们称之为MyListWidget。根据变量的值MyListWidget初始化它自己的小部件。显然,如果您更改和的值,则不会发生任何事情,因为它创建了值中。我怎样才能强制重建?我知道在这个例子中我们可以移动我们在方法中所做的事情。但在我真正的问题中,我无法移动我在方法中所做的事情。initStatecountcountSetStateMyListWidgetinitStateMyListWidgetinitStatebuildinitStatebuild

这是完整的代码示例:

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 {
  MyHomePage({Key? key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int count = 5;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Row(
      children: [
        Expanded(
          child: MaterialButton(
            child: Text('Click me'),
            color: Colors.red,
            onPressed: () {
              setState(() {
                count++;
              });
            },
          ),
        ),
        MyListWidget(count),
      ],
    ));
  }
}

class MyListWidget extends StatefulWidget {
  final int count;

  const MyListWidget(this.count, {Key? key}) : super(key: key);

  @override
  _MyListWidgetState createState() => _MyListWidgetState();
}

class _MyListWidgetState extends State<MyListWidget> {
  late List<int> displayList;

  @override
  void initState() {
    super.initState();
    displayList = List.generate(widget.count, (int index) => index);
  }

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: ListView.builder(
        itemBuilder: (BuildContext context, int index) => ListTile(
          title: Text(displayList[index].toString()),
        ),
        itemCount: displayList.length,
      ),
    );
  }
}

Run Code Online (Sandbox Code Playgroud)

Elt*_*kes 34

我认为接受的答案并不准确,Flutter 将保留 的状态,MyListWidget因为它与以前具有相同的类型并且在小部件树中的位置相同。

相反,通过更改其密钥来强制重建小部件:

class _MyHomePageState extends State<MyHomePage> {
  int count = 5;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          Expanded(
            child: MaterialButton(
              child: Text('Click me'),
              color: Colors.red,
              onPressed: () {
                setState(() {
                  count++;
                });
              },
            ),
          ),
          MyListWidget(count, key: ValueKey(count)),
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

在此示例中使用 a意味着仅当实际不同时ValueKey才会重新创建状态。count

或者,您可以监听 中的小部件更改State.didUpdateWidget,您可以在其中将当前状态this.widget与传入的状态进行比较oldWidget,并在必要时更新状态。


Ana*_*eem 1

用这个:

class _MyHomePageState extends State<MyHomePage> {
  int count = 5;
  MyListWidget myListWidget = MyListWidget(5);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Row(
      children: [
        Expanded(
          child: MaterialButton(
            child: Text('Click me'),
            color: Colors.red,
            onPressed: () {
              setState(() {
                 count++;
                 myListWidget = MyListWidget(count);
               });
            },
          ),
        ),
        myListWidget,
      ],
    ));
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这不起作用的原因是,当 StatefulWidget 的父级重建时,StatefulWidget 会重用不在其 State 小部件内的所有内容。StatelessWidgets 被完全销毁并重新重建,但 StatefulWidgets 仅部分重建。请参阅上面 Elte Hupkes 的回答!调用 StatefulWidget 时使用“Key key”属性为我做到了。 (2认同)