Dart中RadioListTile泛型onChanged空检查类型转换崩溃求助
Dart泛型限制下RadioListTile.onChanged的空检查方案
问题核心
直接使用raw类型RadioListTile访问onChanged时,编译器会将其静态类型推断为((dynamic) => void)?,但实际运行时类型是(T?) => void(比如(String?) => void),由于函数类型的逆变特性,两者不兼容,导致类型转换崩溃。
解决方案1:使用泛型函数匹配具体类型
通过泛型参数匹配RadioListTile的实际泛型类型,让编译器正确推断onChanged的类型,无需类型转换即可安全检查null:
void testWidgetOnNullCallback<T>(Widget widget) { if (widget is RadioListTile<T>) { if (widget.onChanged != null) { print('onChanged is not null'); } } } void testIfOnChangeIsNull(Widget widget) { // 编译器会自动推断泛型参数T的类型 testWidgetOnNullCallback(widget); } test('when widget is RadioListTile onChange test', () { RadioListTile<String> widget = RadioListTile( value: 'value', activeColor: Colors.red, toggleable: true, onChanged: (value) => debugPrint('Test'), groupValue: null, ); testIfOnChangeIsNull(widget); });
这个方案完全利用Dart的泛型系统,保证编译时类型安全,不会触发类型转换错误。
解决方案2:通过Object?兼容所有泛型类型
如果不需要关注T的具体类型,仅需检查onChanged是否为null,可以将泛型参数指定为Object?,利用Dart的泛型协变特性(仅适用于空检查场景,若要调用onChanged仍需处理类型):
void testWidgetOnNullCallback(Widget widget) { // 所有RadioListTile<T>都是RadioListTile<Object?>的子类型(协变) if (widget is RadioListTile<Object?>) { if (widget.onChanged != null) { print('onChanged is not null'); } } }
这种方式无需泛型函数,代码更简洁,同样能安全完成空检查。
为什么原方案会崩溃
当使用raw类型RadioListTile时,onChanged的静态类型被推断为((dynamic) => void)?,但实际运行时类型是(T?) => void。由于函数参数是逆变的:(dynamic) => void可以接受任意参数,而(T?) => void只能接受T?类型参数,因此后者无法向上转换为前者,访问时会触发类型转换异常,哪怕只是检查null。
内容的提问来源于stack exchange,提问作者Mike.R
相关产品推荐
相关产品推荐

