Flutter中Main.dart使用Provider结合Socket.IO接收数据报错求助
问题原因
你在initState中传入的context是MyApp组件的上下文,此时MultiProvider还未完成构建,这个上下文无法访问到内部的SocketDataProvider;同时你存储的_providerContext不属于MultiProvider的子树,导致调用Provider.of时出错。
解决方案
调整Socket初始化时机,在MultiProvider构建完成后使用其子树的上下文访问Provider,同时优化生命周期管理避免内存泄漏。
修改后的完整代码
import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import './providers/socket_data_provider.dart'; import 'package:wineasy/screens/dashboard.dart'; import 'package:wineasy/screens/test.dart'; import 'package:socket_io_client/socket_io_client.dart' as IO; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { final player = AudioPlayer(); late IO.Socket socket; @override void initState() { super.initState(); // 初始化Socket实例 socket = IO.io('http://localhost:4848', <String, dynamic>{ 'transports': ['websocket'], 'autoConnect': false }); } void _initializeSocket(BuildContext providerContext) { socket.connect(); socket.onConnect((data) { print('connected'); socket.on('orderToKitchen', (orders) async { // 使用Provider子树的上下文获取实例 Provider.of<SocketDataProvider>(providerContext, listen: false) .setSocketData(orders); await player.play(AssetSource('music/alertTone1.mp3')); }); }); socket.onDisconnect((data) => print('disconnected')); } @override void dispose() { // 断开Socket连接,释放资源 socket.disconnect(); player.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => SocketDataProvider()), ], child: Builder( // 通过Builder获取MultiProvider子树的上下文 builder: (providerContext) { _initializeSocket(providerContext); return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.red), useMaterial3: true, ), home: const Scaffold( body: Test(), ), ); }, ), ); } }
确保SocketDataProvider实现正确
import 'package:flutter/foundation.dart'; class SocketDataProvider extends ChangeNotifier { List<dynamic> _orders = []; List<dynamic> get orders => _orders; // 根据后端返回数据类型调整,若为追加订单可改用addAll void setSocketData(dynamic orders) { _orders = List.from(orders); // 必须调用此方法通知UI更新 notifyListeners(); } }
在其他页面使用数据(示例:Test页面)
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/socket_data_provider.dart'; class Test extends StatelessWidget { const Test({Key? key}) : super(key: key); @override Widget build(BuildContext context) { // 监听Provider数据变化,自动更新UI final socketProvider = Provider.of<SocketDataProvider>(context); return Center( child: socketProvider.orders.isEmpty ? const Text('暂无订单') : ListView.builder( itemCount: socketProvider.orders.length, itemBuilder: (context, index) { final order = socketProvider.orders[index]; return ListTile( title: Text('订单 ${index + 1}'), subtitle: Text(order.toString()), ); }, ), ); } }
内容的提问来源于stack exchange,提问作者Prasenjit Das
相关产品推荐
相关产品推荐

