Flutter:Hero弹窗组件调用Provider报错致应用冻结问题排查
问题分析与解决方案
核心问题
- Provider类型不匹配:主组件中
StreamProvider提供的是单个MyUser?对象,但弹窗组件中尝试获取List<MyUser?>类型的Provider,这会触发找不到对应Provider的异常,直接导致应用冻结。 - 冗余列表操作:弹窗里对用户列表的循环复制完全多余,可能触发不必要的重绘逻辑。
- 空值处理缺失:未过滤用户列表中的空对象,容易导致DropdownMenuItem出现空文本或空值,引发渲染异常。
修复步骤
1. 修正Provider层级与类型
如果需要在弹窗中获取用户列表,需在主组件中添加对应的StreamProvider,确保弹窗上下文能获取到正确的数据流:
void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); runApp(const Hyttekos()); } class Hyttekos extends StatelessWidget { const Hyttekos({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MultiProvider( providers: [ // 保留原单个用户的Provider StreamProvider<MyUser?>.value( initialData: null, value: AuthService().user, ), // 添加用户列表的StreamProvider(假设AuthService有users数据流) StreamProvider<List<MyUser?>>.value( initialData: [], value: AuthService().users, ), ], child: const MaterialApp( home: Wrapper(), ), ); } }
2. 优化弹窗用户列表处理
移除冗余的列表复制,添加空值过滤,避免异常:
@override Widget build(BuildContext context) { // 获取用户列表Provider var board = Provider.of<List<MyUser?>>(context); // 过滤空用户,避免Dropdown出现空内容 List<MyUser?> members = board.where((user) => user != null).toList(); return Center( child: Padding( padding: const EdgeInsets.all(32.0), child: Hero( tag: _heroAddTag, createRectTween: (begin, end) => RectTween(begin: begin, end: end), child: Material( color: Colors.white, elevation: 2, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ DropdownButton<String>( value: _dropDownActivity, hint: const Text("选择活动"), onChanged: _dropDownCallActivity, items: activities.map((String value) { return DropdownMenuItem( value: value, child: Text(value), ); }).toList(), ), DropdownButton<String>( value: _dropDownMember, hint: const Text("选择成员"), onChanged: _dropDownCallMember, items: members.map((MyUser? value) { return DropdownMenuItem( value: value?.uid ?? "", child: Text(value?.name ?? ""), ); }).toList(), ), ], ), ), ), ), ), ), ); }
3. 优化Dropdown的空值逻辑
修正_dropDownCallMember中的冗余判断,同时给Dropdown添加hint属性提升体验:
void _dropDownCallMember(String? selectedValue) { setState(() { _dropDownMember = selectedValue; }); print(_dropDownMember); }
4. 清理冗余参数
弹窗构造函数中的membersToShow参数未被使用,建议删除:
class addActivityPopupCard extends StatefulWidget { const addActivityPopupCard({Key? key}) : super(key: key); @override State<addActivityPopupCard> createState() => _addActivityPopupCardState(); }
内容的提问来源于stack exchange,提问作者Aslak Aarflot Jønsson
相关产品推荐
相关产品推荐

