使用泛型与抽象类时遭遇ProviderNotFound Exception问题求助
问题分析与解决方案
问题描述
在实现基于Provider的抽象组件时,调用Provider.of<T>(ctx)抛出ProviderNotFound异常,核心代码如下:
抽象类代码
abstract class BaseStatelessWidget<T extends BaseStore> extends StatelessWidget with RouteAware { late final T childStore; BaseStatelessWidget({super.key}); @override Widget build(BuildContext context) { childStore = getImplementedStore(); return Provider( create: <T>(_) => childStore, builder: (ctx, __) { final store = Provider.of<T>(ctx, listen: false); // 此处抛出ProviderNotFound异常 store; return _BaseStatefulWidget<T>( builder: buildScreen, ); }, ); } Widget buildScreen(BuildContext context); T getImplementedStore(); }
实现类代码
class Counter extends BaseStatelessWidget<CounterStore> { Counter({super.key}); @override Widget buildScreen(BuildContext context) { return Scaffold( body: Container( color: AppColors.white, child: Column( children: [ Observer( builder: (ctx) { return Text( '${getStore<CounterStore>(ctx).counter} Times Clicked', ); }, ) ], ), ), floatingActionButton: FloatingActionButton( onPressed: () { getStore<CounterStore>(context).increment(); }, child: const Icon(Icons.add), ), ); } @override CounterStore getImplementedStore() { return getIt<CounterStore>(); } } T getStore<T extends BaseStore>(BuildContext context) { return Provider.of<T>(context, listen: false); }
核心错误点
- StatelessWidget的可变状态违规:StatelessWidget是不可变组件,
build方法会被多次触发,每次执行childStore = getImplementedStore();都会重新赋值,既违反设计原则,也会导致Store实例重复获取,引发状态不一致。 - Provider注册与获取时机冲突:在Provider的
builder函数中立即调用Provider.of<T>(ctx)时,当前Provider的实例还未完成上下文注入,此时上下文无法识别该Provider,直接抛出异常。 - 泛型显式指定冗余:
create: <T>(_) => childStore中显式指定<T>属于冗余操作,结合Dart泛型擦除机制,会导致Provider无法正确匹配注入类型。
修复后的代码
修改抽象类为StatefulWidget(正确持有状态)
abstract class BaseStatelessWidget<T extends BaseStore> extends StatefulWidget with RouteAware { const BaseStatelessWidget({super.key}); @override State<BaseStatelessWidget<T>> createState() => _BaseStatelessWidgetState<T>(); Widget buildScreen(BuildContext context); T getImplementedStore(); } class _BaseStatelessWidgetState<T extends BaseStore> extends State<BaseStatelessWidget<T>> { late final T childStore; @override void initState() { super.initState(); // 在initState中初始化Store,仅执行一次 childStore = widget.getImplementedStore(); } @override Widget build(BuildContext context) { return Provider( // 移除显式泛型,让类型自动推导 create: (_) => childStore, // 使用child替代builder,避免时机冲突 child: _BaseStatefulWidget<T>( builder: widget.buildScreen, ), ); } }
实现类无需修改
原Counter组件和getStore函数可直接复用,修复后Provider已正确注入上下文,后续在buildScreen中通过getStore或Provider.of都能正常获取实例。
关键修复说明
- 改为
StatefulWidget并在initState中初始化childStore,确保Store实例仅被获取一次,符合组件生命周期规范。 - 用Provider的
child参数替代builder,避免在Provider未完成注入时提前获取实例。 - 移除
create方法中的显式泛型指定,依赖Dart自动类型推导,避免泛型擦除导致的匹配问题。
内容的提问来源于stack exchange,提问作者Purushotam Kumar
相关产品推荐
相关产品推荐

