在屏幕上包装更新,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 文档,继承是:
Object Diagnosticable DiagnosticTree Widget RenderObjectWidget MultiChildRenderObjectWidget Wrap
Object Diagnosticable DiagnosticableTree Widget StatelessWidget ScrollView BoxScrollView ListView
Object Diagnosticable DiagnosticableTree Widget StatelessWidget ScrollView BoxScrollView GridView
所以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
我的应用程序
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 文档,继承是:
Object Diagnosticable DiagnosticTree Widget RenderObjectWidget MultiChildRenderObjectWidget Wrap
Object Diagnosticable DiagnosticableTree Widget StatelessWidget ScrollView BoxScrollView ListView
Object Diagnosticable DiagnosticableTree Widget StatelessWidget ScrollView BoxScrollView GridView
所以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