使用 socket.io client in dart 在不同地方使用单个实例
use socket.io client in dart in different places with a single instance
我使用 Bloc 和存储库,
我将在项目的不同地方使用套接字。
每个 api 包都有自己的事件,但共享同一个套接字。
我想连接一次并在多个地方和包中使用它。
这可能吗?
// use socket in multiple files
final socket = SocketApi().init();
在 javascript 我会导出 { socket }
包:https://pub.dev/packages/socket_io_client
更新:即使套接字是静态的,也可以多次调用和连接套接字初始化函数,并检查它是否已经连接
import 'dart:async';
import 'package:ngi_api/ngi_api.export.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;
class StreamSocketController<T> {
StreamSocketController() {
print('Init Stream controller ${T.toString()}');
}
final _socketResponse = StreamController<T>();
void Function(T) get addResponse => _socketResponse.sink.add;
Stream<T> get getResponse => _socketResponse.stream;
void dispose() {
_socketResponse.close();
}
}
class SocketApi {
// Factry constructor to retutn same static instance everytime you create any object.
factory SocketApi() {
return _socketApi;
}
// An internal private constructor to access it for only once for static instance of class.
SocketApi._internal();
static void init() {
print('socket init connected: ${socket.connected}');
if (socket.connected == false) {
socket.connect();
socket.on('server:connected', (dynamic data) {
print(
'socket instance created and connected',
);
socket.emit(
'user:connected',
<dynamic, dynamic>{'user': Environment.user},
);
});
socket.on('unauthorized', (dynamic data) {
print('Unauthorized');
});
socket.onError(
(dynamic error) => {print(error), print('socket error')},
);
socket.onDisconnect((dynamic data) {
print('socket instance disconnected');
});
} else {
print('socket instance already connected');
}
}
// A static private instance to access _socketApi from inside class only
static final SocketApi _socketApi = SocketApi._internal();
static IO.Socket socket = IO.io(
TcFleetTunEnvironment.socketURL,
IO.OptionBuilder()
.setTransports(['websocket'])
.disableAutoConnect()
.enableForceNewConnection()
.setTimeout(5000)
.setReconnectionDelay(10000)
.enableReconnection()
.setQuery(
<dynamic, dynamic>{'token': Environment.token},
)
.build(),
);
// All socket related functions.
static Stream<Asset> getAsset() async* {
final streamSocket = StreamSocketController<Asset>();
try {
socket.on('newMsg', (dynamic data) {
try {
streamSocket
.addResponse(Asset.fromJson(data as Map<String, dynamic>));
} catch (e, stackTrace) {
print('Exception newMsg');
print(e);
print(stackTrace);
print(data);
}
});
yield* streamSocket.getResponse.take(20);
} catch (e) {
print('Exception getAsset');
print(e);
} finally {
print('Stream controller asset closed');
socket.off('newMsg');
streamSocket.dispose();
}
}
}
//main
void main() async {
SocketApi.init();
SocketApi.init();
SocketApi.getAsset().listen(
(Asset data) {
print('Asset.1: ${data.name}');
},
cancelOnError: false,
onError: print,
onDone: () {
print('*** asset.1 stream controller Done ***');
},
);
}
这是我多次调用 socketApi.init() 的结果,已连接的套接字永远不会打印出来,而是创建一个新连接
这是我的依赖文件
要实现所需的功能,您需要为 Socket IO 插件创建一个 class,它将与 SocketIO 包的代码进行所有交互,并且您还需要创建一个工厂构造函数,因此使用相同的 SocketApi 对象整个应用程序。
工厂构造函数示例。
class SocketApi {
// A static private instance to access _socketApi from inside class only
static final SocketApi _socketApi = SocketApi._internal();
// An internal private constructor to access it for only once for static instance of class.
SocketApi._internal();
// Factry constructor to retutn same static instance everytime you create any object.
factory SocketApi() {
return _socketApi;
}
// All socket related functions.
}
用法
SocketApi socketApi = SocketApi();
您可以了解有关工厂构造函数的更多信息here。
是的,当然可以。您可以制作一个单例服务并在全球范围内访问它。当您需要确保只创建 class 的单个实例,并且您希望提供对其的全局访问点时,单例设计模式会很有帮助。
class SocketSingleton {
Socket _socket;
SocketSingleton._privateConstructor();
static final SocketSingleton _instance =
SocketSingleton._privateConstructor();
static SocketSingleton get instance => _instance;
static SocketSingleton get socket => _socket;
initSocket() {
_socket = SocketApi().init();
}
}
我使用 Bloc 和存储库, 我将在项目的不同地方使用套接字。 每个 api 包都有自己的事件,但共享同一个套接字。 我想连接一次并在多个地方和包中使用它。 这可能吗?
// use socket in multiple files
final socket = SocketApi().init();
在 javascript 我会导出 { socket }
包:https://pub.dev/packages/socket_io_client
更新:即使套接字是静态的,也可以多次调用和连接套接字初始化函数,并检查它是否已经连接
import 'dart:async';
import 'package:ngi_api/ngi_api.export.dart';
import 'package:socket_io_client/socket_io_client.dart' as IO;
class StreamSocketController<T> {
StreamSocketController() {
print('Init Stream controller ${T.toString()}');
}
final _socketResponse = StreamController<T>();
void Function(T) get addResponse => _socketResponse.sink.add;
Stream<T> get getResponse => _socketResponse.stream;
void dispose() {
_socketResponse.close();
}
}
class SocketApi {
// Factry constructor to retutn same static instance everytime you create any object.
factory SocketApi() {
return _socketApi;
}
// An internal private constructor to access it for only once for static instance of class.
SocketApi._internal();
static void init() {
print('socket init connected: ${socket.connected}');
if (socket.connected == false) {
socket.connect();
socket.on('server:connected', (dynamic data) {
print(
'socket instance created and connected',
);
socket.emit(
'user:connected',
<dynamic, dynamic>{'user': Environment.user},
);
});
socket.on('unauthorized', (dynamic data) {
print('Unauthorized');
});
socket.onError(
(dynamic error) => {print(error), print('socket error')},
);
socket.onDisconnect((dynamic data) {
print('socket instance disconnected');
});
} else {
print('socket instance already connected');
}
}
// A static private instance to access _socketApi from inside class only
static final SocketApi _socketApi = SocketApi._internal();
static IO.Socket socket = IO.io(
TcFleetTunEnvironment.socketURL,
IO.OptionBuilder()
.setTransports(['websocket'])
.disableAutoConnect()
.enableForceNewConnection()
.setTimeout(5000)
.setReconnectionDelay(10000)
.enableReconnection()
.setQuery(
<dynamic, dynamic>{'token': Environment.token},
)
.build(),
);
// All socket related functions.
static Stream<Asset> getAsset() async* {
final streamSocket = StreamSocketController<Asset>();
try {
socket.on('newMsg', (dynamic data) {
try {
streamSocket
.addResponse(Asset.fromJson(data as Map<String, dynamic>));
} catch (e, stackTrace) {
print('Exception newMsg');
print(e);
print(stackTrace);
print(data);
}
});
yield* streamSocket.getResponse.take(20);
} catch (e) {
print('Exception getAsset');
print(e);
} finally {
print('Stream controller asset closed');
socket.off('newMsg');
streamSocket.dispose();
}
}
}
//main
void main() async {
SocketApi.init();
SocketApi.init();
SocketApi.getAsset().listen(
(Asset data) {
print('Asset.1: ${data.name}');
},
cancelOnError: false,
onError: print,
onDone: () {
print('*** asset.1 stream controller Done ***');
},
);
}
这是我多次调用 socketApi.init() 的结果,已连接的套接字永远不会打印出来,而是创建一个新连接
这是我的依赖文件
要实现所需的功能,您需要为 Socket IO 插件创建一个 class,它将与 SocketIO 包的代码进行所有交互,并且您还需要创建一个工厂构造函数,因此使用相同的 SocketApi 对象整个应用程序。
工厂构造函数示例。
class SocketApi {
// A static private instance to access _socketApi from inside class only
static final SocketApi _socketApi = SocketApi._internal();
// An internal private constructor to access it for only once for static instance of class.
SocketApi._internal();
// Factry constructor to retutn same static instance everytime you create any object.
factory SocketApi() {
return _socketApi;
}
// All socket related functions.
}
用法
SocketApi socketApi = SocketApi();
您可以了解有关工厂构造函数的更多信息here。
是的,当然可以。您可以制作一个单例服务并在全球范围内访问它。当您需要确保只创建 class 的单个实例,并且您希望提供对其的全局访问点时,单例设计模式会很有帮助。
class SocketSingleton {
Socket _socket;
SocketSingleton._privateConstructor();
static final SocketSingleton _instance =
SocketSingleton._privateConstructor();
static SocketSingleton get instance => _instance;
static SocketSingleton get socket => _socket;
initSocket() {
_socket = SocketApi().init();
}
}