Flutter如何实现按钮成对参数的编译时必填校验?
实现配套参数的编译时检查
可以通过以下几种方式实现,确保secondaryButtonText和secondaryButtonOnTap必须同时传入或都不传入,触发编译错误:
方案1:使用命名构造函数拆分场景
定义两个命名构造函数,分别对应「仅主按钮」和「主按钮+副按钮」的场景,强制副按钮的两个参数必须同时传入:
import 'package:flutter/material.dart'; class ButtonPlacement extends StatelessWidget { // 仅主按钮的构造函数 const ButtonPlacement.onlyPrimary({ required this.primaryButtonText, required this.primaryButtonOnTap, super.key, }) : secondaryButtonText = null, secondaryButtonOnTap = null; // 包含副按钮的构造函数(必须同时传入两个副按钮参数) const ButtonPlacement.withSecondary({ required this.primaryButtonText, required this.primaryButtonOnTap, required this.secondaryButtonText, required this.secondaryButtonOnTap, super.key, }); final String primaryButtonText; final VoidCallback primaryButtonOnTap; final String? secondaryButtonText; final VoidCallback? secondaryButtonOnTap; @override Widget build(BuildContext context) { // 你的布局实现 return Column( children: [ ElevatedButton( onPressed: primaryButtonOnTap, child: Text(primaryButtonText), ), if (secondaryButtonText != null && secondaryButtonOnTap != null) TextButton( onPressed: secondaryButtonOnTap, child: Text(secondaryButtonText!), ), ], ); } }
调用示例:
// 仅主按钮,合法 ButtonPlacement.onlyPrimary( primaryButtonText: "主按钮", primaryButtonOnTap: () {}, ); // 主+副按钮,合法 ButtonPlacement.withSecondary( primaryButtonText: "主按钮", primaryButtonOnTap: () {}, secondaryButtonText: "副按钮", secondaryButtonOnTap: () {}, ); // 仅传副按钮文本,编译报错(因为withSecondary构造函数要求两个参数都传) ButtonPlacement.withSecondary( primaryButtonText: "主按钮", primaryButtonOnTap: () {}, secondaryButtonText: "副按钮", );
方案2:封装副按钮参数为单独类
把secondaryButtonText和secondaryButtonOnTap封装成一个配置类,让ButtonPlacement只接受这个类的可选参数,确保要么不传,要么传完整的配置:
import 'package:flutter/material.dart'; // 副按钮配置类,强制必须同时传入文本和点击回调 class SecondaryButtonConfig { const SecondaryButtonConfig({ required this.text, required this.onTap, }); final String text; final VoidCallback onTap; } class ButtonPlacement extends StatelessWidget { const ButtonPlacement({ required this.primaryButtonText, required this.primaryButtonOnTap, this.secondaryConfig, super.key, }); final String primaryButtonText; final VoidCallback primaryButtonOnTap; final SecondaryButtonConfig? secondaryConfig; @override Widget build(BuildContext context) { return Column( children: [ ElevatedButton( onPressed: primaryButtonOnTap, child: Text(primaryButtonText), ), if (secondaryConfig != null) TextButton( onPressed: secondaryConfig!.onTap, child: Text(secondaryConfig!.text), ), ], ); } }
调用示例:
// 仅主按钮,合法 ButtonPlacement( primaryButtonText: "主按钮", primaryButtonOnTap: () {}, ); // 主+副按钮,合法 ButtonPlacement( primaryButtonText: "主按钮", primaryButtonOnTap: () {}, secondaryConfig: SecondaryButtonConfig( text: "副按钮", onTap: () {}, ), ); // 仅传部分副按钮参数,编译报错(因为SecondaryButtonConfig要求两个参数都传) ButtonPlacement( primaryButtonText: "主按钮", primaryButtonOnTap: () {}, secondaryConfig: SecondaryButtonConfig( text: "副按钮", ), );
补充:运行时断言检查(辅助)
如果需要额外的运行时保障,可以在构造函数中添加断言,防止意外出现参数不匹配的情况:
const ButtonPlacement({ required this.primaryButtonText, required this.primaryButtonOnTap, this.secondaryButtonText, this.secondaryButtonOnTap, super.key, }) : assert( (secondaryButtonText == null && secondaryButtonOnTap == null) || (secondaryButtonText != null && secondaryButtonOnTap != null), "secondaryButtonText和secondaryButtonOnTap必须同时传入或都不传入", );
不过这种方式是运行时检查,不会触发编译错误,只能作为上述编译时方案的补充。
内容的提问来源于stack exchange,提问作者user14624595
相关产品推荐
相关产品推荐

