在屏幕上包装更新,ListView 和 GridView 不会。为什么?

Wrap updates on screen, ListView and GridView do not. Why?

我的应用程序

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(home: Scaffold(body: Grid())));

class Grid extends StatefulWidget {
  @override
  _GridState createState() => _GridState();
}

class _GridState extends State<Grid> {

  List<Widget> pieces = [Text('a'), Text('b'), Text('c')];

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: GestureDetector(
        onTap: () => setState(() => pieces[0] = Text('*')),
        child: Wrap(children: pieces),
        // child: ListView(children: pieces),
        // child: GridView.count(crossAxisCount: 3, children: pieces),
      ),
    );
  }
}

问题

点击环绕后,屏幕上的 a' 变为 '*' - 正如预期的那样

当我用 ListView 或 GridView 替换 Wrap 时,'a' 没有改变。为什么?

'stable' 和 'master'

上的行为相同
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.12.13+hotfix.9, on Linux, locale en_GB.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[✓] Android Studio (version 3.6)
[✓] IntelliJ IDEA Community Edition (version 2019.3)
[✓] VS Code (version 1.44.0)
[✓] Connected device (1 available)

• No issues found!
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, v1.18.0-5.0.pre.89, on Linux, locale en_GB.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[✓] Android Studio (version 3.6)
[✓] IntelliJ IDEA Community Edition (version 2019.3)
[✓] VS Code (version 1.44.0)
[✓] Connected device (1 available)

• No issues found!

钥匙好像没用

有人 post 编辑并建议使用密钥 - 但在我感谢他们之前删除了 post。使用这样的键 ...

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(home: Scaffold(body: Grid())));

class Grid extends StatefulWidget {
  @override
  _GridState createState() => _GridState();
}

class _GridState extends State<Grid> {

  List<Widget> pieces = [Text('a', key:UniqueKey()), Text('b', key:UniqueKey()), Text('c', key:UniqueKey())];

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: GestureDetector(
        onTap: () => setState(() => pieces[0] = Text('*', key:UniqueKey())),
        child: Wrap(children: pieces),
        // child: ListView(children: pieces),
        // child: GridView.count(crossAxisCount: 3, children: pieces),
      ),
    );
  }
}

...没有区别。

因为 Wrap 非常不同?

根据 Flutter 文档,继承是:

所以ListView和GridView都与Wrap有很大的不同。这能说明问题吗?如果有,如何解决?

我认为您需要像这样向 GridView 添加一个唯一的 key 属性

GridView.count(crossAxisCount: 3, children: pieces, key: UniqueKey());

或在别处使用GridView.builder构造函数

child: GridView.builder(
  itemCount: 3,
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
  itemBuilder: (context, index) => pieces[index],
),

尝试使用 ValueListenableBuilder<T> class。 它可以 重新呈现 您真正想要的位置,而无需重建整个小部件树,如果您在当前页面中使用昂贵的小部件,那将是很棒的。

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('title')
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You're list should be generating below :'),
            ValueListenableBuilder(
              builder: (BuildContext context, int value, Widget child) {
                // This builder will only get called when the index
                // is updated.
                return Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                    Text('pieces[index]'),
                    child,
                  ],
                );
              },
              valueListenable: _counter,
              // The child parameter is most helpful if the child is
              // expensive to build and does not depend on the value from
              // the notifier.
              child: expensiveWidget,
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.plus_one),
        onPressed: () => index++,
      ),
    );
  }
}

您还可以查看完整文档here