一直很困惑。
比如说,一个页面有 4 个一样的元素,实现方式:
1 、写个方法,接收 icon 和 text ,返回 Widget ,代码整齐美观。
2 、直接复制粘贴 4 份 widget ,每个都是 const 。
正常人的脑回路,应该都是 1.
但曾经试过把一个 App ,所有能加 const 的地方全部加上,感觉效果是肉眼可见的。
当然,最终的答案可能是平衡在哪里的问题。
方法1:
const Row(
children: ['aa', 'bb'].map(
(e) => Image(
image: AssetImage(e),
fit: BoxFit.fill,
width: 20,
height: 20,
),
).toList(),
);
或者
const Row(
children:[
_getImage('xxxxx'),
_getImage('yyyyy'),
],
);
Widget _getImage(String asset){
return Image(
image: AssetImage(asset),
fit: BoxFit.fill,
width: 20,
height: 20,
);
}
方法2:
const Row(
children: [
Image(
image: AssetImage(xxxxx),
fit: BoxFit.fill,
width: 20,
height: 20,
),
Image(
image: AssetImage(yyyyy),
fit: BoxFit.fill,
width: 20,
height: 20,
),
],
);
方法1:
Row(
children: ['aa', 'bb'].map(
(e) => Image(
image: AssetImage(e),
fit: BoxFit.fill,
width: 20,
height: 20,
),
).toList(),
);
或者
Row(
children:[
_getImage('xxxxx'),
_getImage('yyyyy'),
],
);
Widget _getImage(String asset){
return Image(
image: AssetImage(asset),
fit: BoxFit.fill,
width: 20,
height: 20,
);
}
方法2:
const Row(
children: [
Image(
image: AssetImage(xxxxx),
fit: BoxFit.fill,
width: 20,
height: 20,
),
Image(
image: AssetImage(yyyyy),
fit: BoxFit.fill,
width: 20,
height: 20,
),
],
);
这个才是,刚复制时忘记删除const了
1
w19961009 2023-12-06 11:24:16 +08:00
提炼方法变成提炼成 widget ,新 widget 在构造方法 const 修饰
|
2
purringpal 2023-12-06 11:25:39 +08:00 via iPhone
按我的理解,你在 return 的时候加 const ,不就一样了,而且你 IDE 不会提示的吗
|
3
zqlcrow OP @purringpal
参数都是动态传入,怎么能加 const 呢。 比如 Image( image: AssetImage(imageUrl), fit: BoxFit.fill, width:20, height: 20, ), imageUrl 是动态传入的,那么这个 Image 就不能是 const 的。 |
4
zqlcrow OP |
5
AoEiuV020JP 2023-12-06 11:39:04 +08:00
我有些不理解的是明明 flutter 那个 dart fix 可以自动把整个页面所有能上 const 的控件全都上齐了,那为什么还要人写?编译运行时自动补上不就好了,
类似 jdk 8 可以省略传入匿名内部类变量的 final 修饰,既然编译器能知道这里要加 final ,那就干脆自动加上省得写了, 另外楼主的问题,1 确实不是 flutter 推荐做法,封装成方法后参数是变量,这里用变量初始化的控件是“不能”加 const 的,而方法调用这里哪怕传入的是常量,flutter 也是“不支持”给方法调用加 const 的,结果就是封装成方法就无法使用 const ,所以 ide 不会提示加,@purringpal |
6
zqlcrow OP @AoEiuV020JP 可是 2 的写法,未免太弱智了。
|
7
AoEiuV020JP 2023-12-06 11:44:40 +08:00
@zqlcrow #4 首次 build 就看有没有完全相同的控件了,按你说的一个页面 4 个一样的控件,用 const 那最终就能复用,少初始化几个控件,性能更好是自然的,
|
8
AoEiuV020JP 2023-12-06 11:48:04 +08:00
@zqlcrow #6 推荐做法就是一楼的方案,没有其他的选择了,
2 是任何编程语言都不推荐的写法,和 flutter 无关, |
9
zqlcrow OP |
10
AoEiuV020JP 2023-12-06 11:51:07 +08:00
@zqlcrow #9 这个情况,理论上不涉及复用的话 const 没有什么好处,首次 build 创建四个 const 控件和创建四个普通控件应当是没什么区别的,
|
11
purringpal 2023-12-06 11:51:45 +08:00
@zqlcrow 了解了。
不过我的角度是 const 本身,如果一个对象是可以在编译时确定的,那无论你封装多少层,它应该依然可以在编译时确定,反之亦然。 所以如果你的传参是常量,那就不要传参,在函数里直接赋值,如果传参不是常量,那又何来 const 。可解? |
12
AoEiuV020JP 2023-12-06 11:58:07 +08:00
@zqlcrow #9 不过考虑现实,实际用户首次加载一个页面也可能因为加载设置和异步数据之类的原因多次刷新,这时候 const 好处就体现出来了,这部分可以避免重复初始化,哪怕在用户看来这个页面明明只是第一次加载,
|
13
tool2d 2023-12-06 11:58:27 +08:00
看性能需求吧。
处理业务的时候,我大部分时候都不加 const ,代码运行慢点就慢点。 但是我看老外和大公司代码,基本上都是加 const 的。 |
14
zqlcrow OP @AoEiuV020JP 补充了下 1 和 2 的例子
|
15
AoEiuV020JP 2023-12-06 12:02:33 +08:00
@purringpal #11 主要还是“不支持”,你说这个理论上是可以的,但可能是分析难度的考虑,flutter”不支持“对方法调用指定 const ,
也就是你有, Text('1') Text('2') Text('3') Text('4') 四个控件这样写就都可以是 const , 但如果你封闭成, Widget create(String t) { return Text(t); } 然后调用, create('1') create('2') create('3') create('4') 这时候两边都是不能 const 的,内部因为这个 t 是”变量“,所以 Text 不能设置 const , 外部因为方法调用”不支持“设置 const ,毕竟不好分析你这方法内部有没有使用什么参数以外的其他变量, |
16
AoEiuV020JP 2023-12-06 12:11:29 +08:00
@zqlcrow #14 用 map 这个确实纠结了,但封装成 widget 依然是 flutter 上唯一正确的解,哪怕觉得可能不如 map 简洁直观,但也不差,
const Row( children: [ ImageA(xxxxx), ImageA(yyyyy), ], ); |
17
purringpal 2023-12-06 12:35:44 +08:00
@AoEiuV020JP 明白了,👍
既然是唯一解,如果有个插件能一键封装,可能就最优解了。 |