泛型InheritedWidget嵌套泛型StatefulWidget时inheritFromWidgetOfExactType失效
解决Flutter泛型StatefulWidget包裹泛型InheritedWidget时无法找到的问题
这个问题我之前也遇到过,核心原因是Dart泛型类型擦除加上旧的inheritFromWidgetOfExactType方法在泛型嵌套场景下的类型匹配缺陷。结合你用Bloc模式的需求,我给你一套完整的解决方案,完全支持嵌套使用:
方案一:改用官方推荐的dependOnInheritedWidgetOfExactType方法
Flutter已经废弃了inheritFromWidgetOfExactType,取而代之的dependOnInheritedWidgetOfExactType对泛型类型的处理更可靠,不需要手动获取Type对象,直接通过泛型参数就能精准匹配对应的InheritedWidget。
修改你的BlocProvider代码:
import 'package:flutter/widgets.dart'; abstract class BlocBase { void dispose(); } class BlocProvider<T extends BlocBase> extends InheritedWidget { final T bloc; const BlocProvider({ Key? key, required this.bloc, required Widget child, }) : assert(bloc != null), assert(child != null), super(key: key, child: child); static T of<T extends BlocBase>(BuildContext context) { // 直接通过泛型参数匹配,避开手动获取Type的擦除问题 final provider = context.dependOnInheritedWidgetOfExactType<BlocProvider<T>>(); assert(provider != null, "找不到对应的BlocProvider<$T>,请确保它在当前context的组件树中"); return provider!.bloc; } @override bool updateShouldNotify(BlocProvider oldWidget) => false; }
方案二:修正BlocHolder的泛型传递逻辑
你的BlocHolder代码存在泛型参数传递不严谨的问题,会导致类型匹配时出现偏差,需要调整State类的泛型绑定:
class BlocHolder<T extends BlocBase> extends StatefulWidget { final Widget child; final T Function() createBloc; final bool wantKeepAlive; BlocHolder({ required this.child, required this.createBloc, this.wantKeepAlive = false, }); @override _BlocHolderState<T> createState() => _BlocHolderState<T>(); } class _BlocHolderState<T extends BlocBase> extends State<BlocHolder<T>> with AutomaticKeepAliveClientMixin<BlocHolder<T>> { late T _bloc; @override void initState() { super.initState(); _bloc = widget.createBloc(); } @override Widget build(BuildContext context) { // 使用AutomaticKeepAliveClientMixin必须调用super.build super.build(context); return BlocProvider( child: widget.child, bloc: _bloc, ); } @override void dispose() { _bloc.dispose(); super.dispose(); } @override bool get wantKeepAlive => widget.wantKeepAlive; }
为什么这样能解决问题?
dependOnInheritedWidgetOfExactType的泛型优势:这个方法内部会直接根据你传入的泛型参数(比如BlocProvider<BlocTop>)去组件树中查找对应的InheritedWidget,彻底避开了手动获取Type时的泛型擦除问题。- 修正BlocHolder的泛型绑定:原来的
_BlocHolderState继承自State<BlocHolder>,没有绑定泛型参数T,导致widget的类型被擦除;现在改成State<BlocHolder<T>>后,泛型参数能完整传递到BlocProvider中,确保类型匹配精准。
嵌套BlocProvider的支持验证
这个方案完全支持多Bloc嵌套场景,比如你可以这样使用:
BlocHolder<BlocA>( createBloc: () => BlocA(), child: BlocHolder<BlocB>( createBloc: () => BlocB(), child: Builder( builder: (context) { final blocA = BlocProvider.of<BlocA>(context); final blocB = BlocProvider.of<BlocB>(context); return YourBusinessWidget(); }, ), ), )
BlocProvider.of<T>会自动找到当前context最近的对应类型的BlocProvider,完全符合Bloc模式的嵌套需求。
内容的提问来源于stack exchange,提问作者AlexKost
相关产品推荐
相关产品推荐

