You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 09:45:59