如何在StatefulWidget的State类中调用构造函数声明的onChanged属性
解决方案
你可以通过给Foo类添加两个分别对应int和double类型的回调属性,在命名构造函数中初始化对应属性的方式,让_FooState能够安全访问并调用回调。以下是具体实现:
方案一:拆分回调属性(类型安全,推荐)
这种方式直接为每种类型声明独立的回调属性,避免类型转换,代码清晰且类型安全:
class Foo extends StatefulWidget { // 对应int类型的回调 final ValueChanged<int>? onIntChanged; // 对应double类型的回调 final ValueChanged<double>? onDoubleChanged; // int类型构造函数:只初始化onIntChanged,onDoubleChanged置为null const Foo.int({super.key, this.onIntChanged}) : onDoubleChanged = null; // double类型构造函数:只初始化onDoubleChanged,onIntChanged置为null const Foo.double({super.key, this.onDoubleChanged}) : onIntChanged = null; @override State<Foo> createState() => _FooState(); } class _FooState extends State<Foo> { @override Widget build(BuildContext context) { // 根据当前实例的类型调用对应回调 widget.onIntChanged?.call(22); // 调用int类型回调 // 或者根据业务逻辑选择调用: // widget.onDoubleChanged?.call(22.5); return const Placeholder(); } }
使用方式和你原来的代码一致,且回调参数类型会被正确推导:
// int类型调用 Foo.int(onIntChanged: (val) { // val的类型为int print(val.runtimeType); // 输出 int }), // double类型调用 Foo.double(onDoubleChanged: (val) { // val的类型为double print(val.runtimeType); // 输出 double }),
方案二:单回调+类型标识
如果你希望只用一个回调属性,可以通过存储类型标识来确保调用时传入正确类型的值,不过这种方式需要类型转换,不如方案一安全:
class Foo extends StatefulWidget { final ValueChanged<dynamic>? onChanged; // 存储当前实例的数值类型 final Type valueType; const Foo.int({super.key, ValueChanged<int>? onChanged}) : onChanged = onChanged as ValueChanged<dynamic>?, valueType = int; const Foo.double({super.key, ValueChanged<double>? onChanged}) : onChanged = onChanged as ValueChanged<dynamic>?, valueType = double; @override State<Foo> createState() => _FooState(); } class _FooState extends State<Foo> { @override Widget build(BuildContext context) { // 根据类型标识传入对应类型的值 if (widget.valueType == int) { widget.onChanged?.call(22); } else if (widget.valueType == double) { widget.onChanged?.call(22.0); } return const Placeholder(); } }
总结
推荐使用方案一,因为它完全避免了类型转换,代码可读性和类型安全性更高,且符合你仅支持int和double两种类型的需求。
内容的提问来源于stack exchange,提问作者pmatatias
相关产品推荐
相关产品推荐

