Flutter 不会使用不同的参数重建相同的小部件
Posted
技术标签:
【中文标题】Flutter 不会使用不同的参数重建相同的小部件【英文标题】:Flutter is not rebuilding same widget with different parameters 【发布时间】:2019-08-09 18:07:47 【问题描述】:我正在使用带有类似子小部件的底部导航,其中仅更改了参数。只有当小部件属于 StatefulWidget 时才会出现问题,否则没有问题,底部导航栏中的指示正在改变,但正文没有改变。
孩子 1:
孩子 2:
实际结果:
class MyHomePage extends StatefulWidget
MyHomePage(Key key, this.title) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
int _counter = 0;
Widget body;
@override
void initState()
// body = getBody(0);
super.initState();
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
elevation: 0,
),
body: body,
bottomNavigationBar: BottomNavigationBar(
currentIndex: _counter,
onTap: (index)
_counter = index;
setState(()
body = getBody(index);
);
,items: [
BottomNavigationBarItem(icon: Icon(Icons.language),title:
Text('HELLO')),
BottomNavigationBarItem(icon: Icon(Icons.security),title:
Text('BYE'))
]),
);
Widget getBody(int pos)
if(pos==0)
// return new Mx(category: 'ALPHA',type: '@',);
return new MyTAbs(category: 'ALPHA',type: '@',);
else
// return new Mx(category:'BETA',type: '#',);
return new MyTAbs(category:'BETA',type: '#',);
class Mx extends StatelessWidget
final String type,category;
Mx(this.type,this.category);
@override
Widget build(BuildContext context)
return new Scaffold(
backgroundColor: getColor(),
body: new Center(
child: Text(category+' '+type),
),
);
Color getColor()
if(category=='ALPHA')
return Colors.red;
else
return Colors.green;
class MyTAbs extends StatefulWidget
final String type,category;
MyTAbs(this.type,this.category);
Tabs createState() => new Tabs(title: category,type: type);
class Tabs extends State<MyTAbs>
final String title,type;
Tabs(this.title,this.type);
@override
Widget build(BuildContext context)
// TODO: implement build
return new Scaffold(
backgroundColor: getColor(),
appBar: AppBar(
title: Text(title+' '+type),
),
);
Color getColor()
if(title=='ALPHA')
return Colors.red;
else
return Colors.green;
我不能使用 statelessWidget,因为里面有一个动态标签部分。
【问题讨论】:
【参考方案1】:通过添加新的 Key 作为参数并传递 UniqueKey 解决了这个问题 喜欢
return new MyTAbs(category: 'ALPHA',type: '@',key: UniqueKey(),);
MyTAbs 类
class MyTAbs extends StatefulWidget
final String type,category;
final Key key;
MyTAbs(@required this.key,this.type,this.category);
Tabs createState() => new Tabs(title: category,type: type,key: key);
标签类
class Tabs extends State<MyTAbs>
final String title,type;
final Key key;
Tabs(this.title,this.type,@required this.key);
@override
@override
Widget build(BuildContext context)
// TODO: implement build
return new Scaffold(
backgroundColor: getColor(),
appBar: AppBar(
title: Text(title+' '+type),
),
);
Color getColor()
if(title=='ALPHA')
return Colors.red;
else
return Colors.green;
钥匙
当小部件重建时,您可以使用键来控制框架与其他小部件匹配的小部件。默认情况下,框架会根据它们的 runtimeType 和它们出现的顺序来匹配当前和先前构建中的小部件。对于键,框架要求两个小部件具有相同的键以及相同的 runtimeType。 more in flutter docs
【讨论】:
非常感谢,今天遇到同样的问题。我想,如果其中一个参数被更改,Widget 将被重建,但不是,initState() 没有被调用。 UniqKey() 工作正常!【参考方案2】:更改您的 Tabs
课程
class Tabs extends State<MyTAbs>
@override
Widget build(BuildContext context)
return new Scaffold(
backgroundColor: getColor(),
appBar: AppBar(
title: Text(widget.category + ' ' + widget.type),
),
);
Color getColor()
if (widget.category == 'ALPHA')
return Colors.red;
else
return Colors.green;
类State
(Tabs
) 仅创建一次。所以在那之后你不能用新参数调用构造函数。但是您可以访问小部件的字段
【讨论】:
【参考方案3】:你在“MyTAbs”传递参数类中的问题
编辑后,现在可以工作了
您不需要将日期从“有状态”类传递给“状态”,只需在状态中使用“widget.parameterName”调用它 编辑后的代码:
class MyHomePage extends StatefulWidget
MyHomePage(Key key, this.title) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
int _counter = 0;
Widget body;
@override
void initState()
// body = getBody(0);
super.initState();
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
elevation: 0,
),
body: body,
bottomNavigationBar: BottomNavigationBar(
currentIndex: _counter,
onTap: (index)
_counter = index;
setState(()
body = getBody(index);
);
,items: [
BottomNavigationBarItem(icon: Icon(Icons.language),title:
Text('HELLO')),
BottomNavigationBarItem(icon: Icon(Icons.security),title:
Text('BYE'))
]),
);
Widget getBody(int pos)
if(pos==0)
// return new Mx(category: 'ALPHA',type: '@',);
return new MyTAbs(category: 'ALPHA',type: '@',);
else
// return new Mx(category:'BETA',type: '#',);
return new MyTAbs(category:'BETA',type: '#',);
class Mx extends StatelessWidget
final String type,category;
Mx(this.type,this.category);
@override
Widget build(BuildContext context)
return new Scaffold(
backgroundColor: getColor(),
body: new Center(
child: Text(category+' '+type),
),
);
Color getColor()
if(category=='ALPHA')
return Colors.red;
else
return Colors.green;
class MyTAbs extends StatefulWidget
final String type,category;
MyTAbs(this.type,this.category);
Tabs createState() => new Tabs();
class Tabs extends State<MyTAbs>
@override
Widget build(BuildContext context)
print(widget.type);
// TODO: implement build
return new Scaffold(
backgroundColor: getColor(),
appBar: AppBar(
title: Text(widget.category+' '+widget.type),
),
);
Color getColor()
if(widget.category=='ALPHA')
return Colors.red;
else
return Colors.green;
【讨论】:
感谢@abdalmonem,您的回答是正确的,但在我的情况下,我正在 Tabs 类中加载选项卡,因此无法使用您的选项卡,而是添加了一个键作为参数,如上所述。你的回答对我来说是一个新信息。以上是关于Flutter 不会使用不同的参数重建相同的小部件的主要内容,如果未能解决你的问题,请参考以下文章
Flutter:检测任何在屏幕上不可见但在小部件树中的小部件的重建
Flutter:StreamProvider 的奇怪行为,使用不完整数据重建的小部件