前提
ここに質問の内容を詳しく書いてください。
Flutterでsocket_io_clientというパッケージを使って双方向通信を実装しています。
サーバー側にemitメソッドでデータを送ることはできたのですが、onメソッドを使うとデータを一時的に受信することはできるのですが、画面遷移してもう一度ページを開くと下記のエラーメッセージが出てしまいます。
実現したいこと
ここに実現したいことを箇条書きで書いてください。
- ▲▲emitメソッドでサーバーにデータを送ったらサーバー側から「入室完了」という文字列を遷移後でも受け取りたい。
発生している問題・エラーメッセージ
[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: Bad state: Tried to use MatchingNotifier after `dispose` was called. Consider checking `mounted`. #0 StateNotifier._debugIsMounted.<anonymous closure> (package:state_notifier/state_notifier.dart:175:9) #1 StateNotifier._debugIsMounted (package:state_notifier/state_notifier.dart:182:6) #2 StateNotifier.state (package:state_notifier/state_notifier.dart:196:12) #3 MatchingNotifier.successJoinRoom.<anonymous closure> (package:quicha/viewModel/matching_viewmodel/matching_notifier.dart:34:17) #4 EventEmitter.emit.<anonymous closure> (package:socket_io_common/src/util/event_emitter.dart:65:14) #5 List.forEach (dart:core-patch/growable_array.dart:416:8) #6 EventEmitter.emit (package:socket_io_common/src/util/event_emitter.dart:64:37) #7 Function._apply (dart:core-patch/function_patch.dart:11:73) #8 Function.apply (dart:core-patch/function_patch.dart:34:12) #9 Socket.onevent (package:socket_io_clien<…>
該当のソースコード
クライアント側
socket_client.dart
1import 'package:socket_io_client/socket_io_client.dart' as IO; 2 3 4class SocketClient { 5 SocketClient(); 6 7 IO.Socket? socket; 8 static SocketClient? _instance; 9 10 SocketClient._internal(){ 11 socket = IO.io("http://localhost:3000/", <String, dynamic>{ 12 'transports' : ["websocket"], 13 'autoConnect' : false, 14 'forceNew' : true, 15 }); 16 17 socket!.connect(); 18 } 19 20 static SocketClient get instance { 21 _instance ??= SocketClient._internal(); 22 23 return _instance!; 24 } 25} 26 27
matching_notifier.dart
1import 'package:flutter_riverpod/flutter_riverpod.dart'; 2import 'package:quicha/model/socket_methods.dart'; 3import 'package:quicha/viewModel/matching_viewmodel/matching_state.dart'; 4 5import '../../model/socket_client.dart'; 6 7final matchingProvider = StateNotifierProvider.autoDispose<MatchingNotifier, MatchingState>( 8 ((ref) => MatchingNotifier()) 9); 10 11 12class MatchingNotifier extends StateNotifier<MatchingState> { 13 14 final _socketClient = SocketClient.instance.socket!; 15 16 MatchingNotifier() : super(const MatchingState()){ 17 } 18 19 void entryRoby() { 20 _socketClient.emit('entryRoby', { 21 'userId' : "12345", 22 }); 23 } 24 25 void getMyRoom() { 26 _socketClient.emit('getMyRoom'); 27 } 28/ 29 void successJoinRoom() { 30 _socketClient.once('successJoinRoom', (data) { 31 state = state.copyWith(successJoinRoom: data); 32 print(data); 33 }); 34 } 35 36 37} 38
matching_screen.dart
1import 'package:flutter/material.dart'; 2import 'package:flutter_hooks/flutter_hooks.dart'; 3import 'package:flutter_riverpod/flutter_riverpod.dart'; 4import 'package:hooks_riverpod/hooks_riverpod.dart'; 5import 'package:quicha/model/socket_client.dart'; 6import 'package:quicha/ui/custom_style.dart'; 7import 'package:quicha/viewModel/matching_viewmodel/matching_notifier.dart'; 8 9class MatchingScreen extends HookConsumerWidget { 10 const MatchingScreen({ 11 Key? key, 12 }) : super(key: key); 13 14 @override 15 Widget build(BuildContext context, ref, ) { 16 17 final state = ref.watch(matchingProvider); 18 final viewModel = ref.read(matchingProvider.notifier); 19 20 21 useEffect((){ 22 //ロビーにエントリーする 23 viewModel.entryRoby(); 24 viewModel.successJoinRoom(); 25 26 }); 27 28 return Scaffold( 29 appBar: AppBar( 30 title: Text("マッチング中……"), 31 backgroundColor: CustomColor.appBarTheme, 32 33 ), 34 body:Container( 35 child: Column( 36 children: [ 37 Text(state.successJoinRoom), 38 ElevatedButton(onPressed: (){ 39 viewModel.getMyRoom(); 40 }, child: Text("TEST")) 41 ], 42 ), 43 ), 44 ); 45 } 46} 47
サーバー側
const { Console } = require('console'); const express = require('express'); const http = require('http'); const app = express(); const server = http.createServer(app); var mongoose = require('mongoose'); const { Socket } = require('socket.io'); const PORT = process.env.PORT || 3000; var io = require('socket.io')(server); app.use(express.json()); var users = new Array(); var numb = 1; io.on('connection', (socket) => { console.log("connected!"); // socket.on('createRoom', async ({nickname}) => { // console.log(nickname); // socket.join("aiueo"); // io.to("aiueo").emit('message', "おいお茶"); // console.log(io.sockets.adapter.rooms.get("aiueo").size); // }); socket.on('entryRoby', ({userID}) => { //テスト var room = "room" + numb; socket.join(room); people = io.sockets.adapter.rooms.get(room).size; console.log(room); console.log(io.sockets.adapter.rooms.get(room).size); if(Number(people) >= 2) { numb++; } }); socket.on('getMyRoom',() => { console.log(socket.rooms); //クライアントのルームに通知 io.to(Array.from(socket.rooms)[1]).emit('successJoinRoom', '入室完了'); }); }); // 3000番ポートでHTTPサーバーを起動 server.listen(PORT,"0.0.0.0", () => { console.log(`listening on port ${PORT}`); });
試したこと
ここに問題に対して試したことを記載してください。
- StateNotifierProviderのautodisposeが悪いのかと思ってautodisposeを外してみた。
補足情報(FW/ツールのバージョンなど)
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。