在 flutter 中强制重建有状态的子部件
Force rebuild of a stateful child widget in flutter
假设我有一个主屏幕(有状态小部件),其中有一个变量 count
作为状态。在这个主屏幕中有一个按钮和另一个有状态的小部件(我们称之为 MyListWidget
。MyListWidget
根据 count
变量的值在 initState
中初始化它自己的小部件。显然,如果你改变 count
的值并调用 SetState
,MyListWidget
中不会发生任何事情,因为它创建了 initState
中的值。我如何强制重建MyListWidget
?
我知道在这个例子中,我们可以将我们在 initState
中所做的事情移动到 build
方法中。但在我真正的问题中,我无法在 build
方法中移动我在 initState
中所做的事情。
完整的代码示例如下:
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,
),
);
}
}
使用这个:
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,
],
));
}
}
我认为接受的答案不准确,Flutter 将保留 MyListWidget
的状态,因为它与之前的类型相同,并且在 widget 树中的位置相同。
相反,通过 changing its key:
强制重建小部件
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)),
],
),
);
}
}
在此示例中使用 ValueKey
意味着仅当 count
实际上不同时才会重新创建状态。
或者,您可以在 State.didUpdateWidget
中监听小部件的变化,在这里您可以将当前 this.widget
与传入的 oldWidget
进行比较,并在必要时更新状态。
假设我有一个主屏幕(有状态小部件),其中有一个变量 count
作为状态。在这个主屏幕中有一个按钮和另一个有状态的小部件(我们称之为 MyListWidget
。MyListWidget
根据 count
变量的值在 initState
中初始化它自己的小部件。显然,如果你改变 count
的值并调用 SetState
,MyListWidget
中不会发生任何事情,因为它创建了 initState
中的值。我如何强制重建MyListWidget
?
我知道在这个例子中,我们可以将我们在 initState
中所做的事情移动到 build
方法中。但在我真正的问题中,我无法在 build
方法中移动我在 initState
中所做的事情。
完整的代码示例如下:
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,
),
);
}
}
使用这个:
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,
],
));
}
}
我认为接受的答案不准确,Flutter 将保留 MyListWidget
的状态,因为它与之前的类型相同,并且在 widget 树中的位置相同。
相反,通过 changing its key:
强制重建小部件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)),
],
),
);
}
}
在此示例中使用 ValueKey
意味着仅当 count
实际上不同时才会重新创建状态。
或者,您可以在 State.didUpdateWidget
中监听小部件的变化,在这里您可以将当前 this.widget
与传入的 oldWidget
进行比较,并在必要时更新状态。