Dart中“常量创建的参数必须是常量表达式”错误解析及代码咨询
咱们先把这个报错的意思掰明白:当你用const关键字创建一个对象的时候,这个对象的所有参数都必须是编译时就能确定值的常量表达式——简单说就是,不能用运行时才会计算出来的变量、非const的对象,或者任何动态生成的内容当参数。编译器需要在编译阶段就完全确定这个const对象的所有细节,不然就会抛出这个错误。
再看你贴的代码,问题出在这儿:你给SliverAppBar加了const修饰,但它里面的FlexibleSpaceBar、Column、Text这些子部件都是用普通的非const构造创建的。这些子部件不属于“编译时常量”,所以编译器就炸了。
给你两个解决办法,选哪个看你的需求:
办法1:让整个对象树都是编译时常量
如果确实需要这个SliverAppBar是const对象,那就要把所有子部件都改成const构造(好在Flutter里大部分基础Widget的构造都支持const)。
Dart 2.5之后有个贴心的优化:在const对象的参数里(也就是const上下文),子构造可以省略外层的const,编译器会自动帮你处理。所以修正后的代码可以写成这样:
const SliverAppBar( pinned: true, expandedHeight: 300.0, // TODO: check out later flexibleSpace: FlexibleSpaceBar( title: Column( mainAxisAlignment: MainAxisAlignment.end, children: <Widget>[ Text('_SliverAppBar'), Text('subtitle'), ], ), background: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('Info'), ], ), ), )
要是你用的是更早的Dart版本,就得给每个子部件都加上const,比如const FlexibleSpaceBar、const Column、const Text这样,不过现在一般都不用这么麻烦了。
办法2:去掉外层的const
如果你根本不需要这个SliverAppBar是编译时常量,那直接把开头的const删掉就行,这样就不用管参数是不是常量了,代码保持你原来的写法就好:
SliverAppBar( pinned: true, expandedHeight: 300.0, // TODO: check out later flexibleSpace: FlexibleSpaceBar( title: Column( mainAxisAlignment: MainAxisAlignment.end, children: <Widget>[ Text('_SliverAppBar'), Text('subtitle'), ], ), background: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('Info'), ], ), ), )
简单总结下:这个报错的核心就是const对象的“全常量”要求,要么满足所有参数都是编译时常量,要么就放弃用const,二选一就行~
内容的提问来源于stack exchange,提问作者DNB5brims

