Flutter升级后BlocProvider出现参数非空隐含默认值为null报错问题
Flutter升级后BlocProvider报错修复方案
所有报错均由Flutter 2.0+版本引入的空安全机制、以及旧版上下文查找API废弃导致,可按以下步骤逐一修复:
1. 构造参数空安全报错修复
你遇到的The parameter can't have a value of 'null'报错是空安全校验触发的,旧版代码的写法不符合空安全规范,修改规则如下:
- 旧版
@required注解替换为空安全内置的required关键字 - 可空的
Key类型添加?标记为可空类型
修改后的两处构造函数代码如下:
// BlocProvider构造函数 BlocProvider({ Key? key, required this.child, required this.bloc, }) : super(key: key); // _BlocProviderInherited构造函数 _BlocProviderInherited({ Key? key, required Widget child, required this.bloc, }) : super(key: key, child: child);
2. of方法API与类型适配修复
2.1 API替换与类型转换
ancestorInheritedElementForWidgetOfExactType确实是已废弃API,官方推荐替换为getElementForInheritedWidgetOfExactType,由于该方法返回通用的InheritedWidget?类型,需要手动强转为你自定义的子类类型,添加强转语句as _BlocProviderInherited<T>?即可。
2.2 返回值可空修改说明
工具提示的将返回值改为T?是完全合法的方案:
- 若你的业务逻辑中调用
of方法时,上下文一定能找到父级的BlocProvider,也可以保留返回T,在返回语句添加!强制非空断言:return provider!.bloc;,这种写法如果找不到对应BlocProvider会直接抛异常 - 更稳妥的方案是保留
T?返回类型,上层调用时自行处理空场景,也可以在方法内部加空校验抛明确的错误提示方便调试
修改后的of方法完整代码如下:
static T? of<T extends BlocBase>(BuildContext context) { final provider = context.getElementForInheritedWidgetOfExactType<_BlocProviderInherited<T>>()?.widget as _BlocProviderInherited<T>?; return provider?.bloc; } // 如果要强制非空版本可以用下面的写法 // static T of<T extends BlocBase>(BuildContext context) { // final provider = context.getElementForInheritedWidgetOfExactType<_BlocProviderInherited<T>>()?.widget as _BlocProviderInherited<T>?; // if (provider == null) { // throw AssertionError('No BlocProvider of type $T found in context'); // } // return provider.bloc; // }
完整修改后代码
import 'package:flutter/material.dart'; abstract class BlocBase { void dispose(); } class BlocProvider<T extends BlocBase> extends StatefulWidget { BlocProvider({ Key? key, required this.child, required this.bloc, }) : super(key: key); final Widget child; final T bloc; @override _BlocProviderState<T> createState() => _BlocProviderState<T>(); static T? of<T extends BlocBase>(BuildContext context) { final provider = context.getElementForInheritedWidgetOfExactType<_BlocProviderInherited<T>>()?.widget as _BlocProviderInherited<T>?; return provider?.bloc; } } class _BlocProviderState<T extends BlocBase> extends State<BlocProvider<T>> { @override void dispose() { widget.bloc.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return _BlocProviderInherited<T>( bloc: widget.bloc, child: widget.child, ); } } class _BlocProviderInherited<T> extends InheritedWidget { _BlocProviderInherited({ Key? key, required Widget child, required this.bloc, }) : super(key: key, child: child); final T bloc; @override bool updateShouldNotify(_BlocProviderInherited oldWidget) => false; }
内容的提问来源于stack exchange,提问作者Bisclavret
相关产品推荐
相关产品推荐

