Flutter实时通信插件socket_io_client_flutter的使用
Flutter实时通信插件socket_io_client_flutter的使用
现在,socket_io_client_flutter
可以作为 Flutter 包从 pub.dev
获取。
版本信息
2.x.x 版本 支持完全的空安全(sound null safety)。可以在 pubspec.yaml
文件中这样添加:
dependencies:
socket_io_client_flutter: ^2.0.0
Dart 3 需要完全的空安全,并且不支持非空安全或不完全的空安全。使用 Dart 3 的 Flutter 版本只能与 socket_io_client_flutter
2.x.x 版本一起工作。使用 Dart 2.12 及以上版本的 Flutter 版本也可以与 socket_io_client_flutter
2.x.x 版本一起工作。
1.x.x 版本 不支持空安全,兼容非空安全和不完全的空安全。可以在 pubspec.yaml
文件中这样添加:
dependencies:
socket_io_client_flutter: ^1.0.2
Dart 1 和 Dart 2 需要非空安全。Dart 2.12 及以上版本支持非空安全以及完全的和不完全的空安全。一些早期使用 Dart 2.12 及以上版本的 Flutter 版本可以自动运行 socket_io_client_flutter
1.x.x 版本,但更新的 Flutter 版本需要使用 --no-sound-null-safety
参数来运行 socket_io_client_flutter
1.x.x 版本。
原始发布说明:将 socket.io-client-dart
移植到 Flutter 而不包含空安全,兼容 Flutter 1.22.6(无空安全)和 Flutter 3.0.2(支持混合空安全)。为 xibbit 添加了无害的长轮询扩展。
在 1.x.x 和 2.x.x 版本中,导入代码如下:
import 'package:socket_io_client_flutter/socket_io_client_flutter.dart';
socket.io-client-dart
这是一个将优秀的 JavaScript Node.js 库 - Socket.io-client v2.0.1~v3.0.3
- 移植到 Dart 的库。
版本信息
socket.io-client-dart | Socket.io Server |
---|---|
v0.9.* ~ v1.* |
v2.* |
v2.* |
v3.* & v4.* |
使用
Dart Server
import 'package:socket_io/socket_io.dart';
void main() {
// Dart server
var io = Server();
var nsp = io.of('/some');
nsp.on('connection', (client) {
print('connection /some');
client.on('msg', (data) {
print('data from /some => $data');
client.emit('fromServer', "ok 2");
});
});
io.on('connection', (client) {
print('connection default namespace');
client.on('msg', (data) {
print('data from default => $data');
client.emit('fromServer', "ok");
});
});
io.listen(3000);
}
Dart Client
import 'package:socket_io_client/socket_io_client.dart' as IO;
void main() {
// Dart client
IO.Socket socket = IO.io('http://localhost:3000');
socket.onConnect((_) {
print('connect');
socket.emit('msg', 'test');
});
socket.on('event', (data) => print(data));
socket.onDisconnect((_) => print('disconnect'));
socket.on('fromServer', (_) => print(_));
}
手动连接
要手动连接套接字,设置选项 autoConnect: false
并调用 .connect()
方法。
例如:
IO.Socket socket = IO.io('http://localhost:3000',
OptionBuilder()
.setTransports(['websocket']) // for Flutter or Dart VM
.disableAutoConnect() // disable auto-connection
.setExtraHeaders({'foo': 'bar'}) // optional
.build()
);
socket.connect();
注意:如果 autoConnect: true
(默认情况下启用),则不应调用 .connect()
,否则会导致所有事件处理器被注册并触发两次。参见 Issue #33。
更新额外头
IO.Socket socket = ... // 创建套接字。
socket.io.options['extraHeaders'] = {'foo': 'bar'}; // 更新额外头。
socket.io.disconnect().connect(); // 手动重新连接套接字。
带确认的发送
IO.Socket socket = ... // 创建套接字。
socket.onConnect((_) {
print('connect');
socket.emitWithAck('msg', 'init', ack: (data) {
print('ack $data') ;
if (data != null) {
print('from server $data');
} else {
print("Null") ;
}
});
});
套接字连接事件
这些事件可以监听。
const List EVENTS = [
'connect',
'connect_error',
'connect_timeout',
'connecting',
'disconnect',
'error',
'reconnect',
'reconnect_attempt',
'reconnect_failed',
'reconnect_error',
'reconnecting',
'ping',
'pong'
];
// 替换 'onConnect' 为上述任意一个事件。
socket.onConnect((_) {
print('connect');
});
确认套接字服务器已收到事件
socket.on('eventName', (data) {
final dataList = data as List;
final ack = dataList.last as Function;
ack(null);
});
在 Flutter 中使用
在 Flutter 环境中(不包括 Flutter Web 环境),它只支持 dart:io
WebSocket,而不是 dart:html
WebSocket 或 Ajax(XHR),因此在这种情况下,创建套接字实例时必须添加 setTransports(['websocket'])
。
例如:
IO.Socket socket = IO.io('http://localhost:3000',
OptionBuilder()
.setTransports(['websocket']) // for Flutter or Dart VM
.setExtraHeaders({'foo': 'bar'}) // optional
.build());
在 Flutter 中使用 Stream 和 StreamBuilder
import 'dart:async';
// STEP1: 设置 Stream
class StreamSocket {
final _socketResponse = StreamController<String>();
void Function(String) get addResponse => _socketResponse.sink.add;
Stream<String> get getResponse => _socketResponse.stream;
void dispose() {
_socketResponse.close();
}
}
StreamSocket streamSocket = StreamSocket();
// STEP2: 在 main.dart 文件的 main 函数中添加此函数并将传入的数据添加到流中
void connectAndListen() {
IO.Socket socket = IO.io('http://localhost:3000',
OptionBuilder()
.setTransports(['websocket']).build());
socket.onConnect((_) {
print('connect');
socket.emit('msg', 'test');
});
// 当从服务器接收到事件时,数据被添加到流中
socket.on('event', (data) => streamSocket.addResponse);
socket.onDisconnect((_) => print('disconnect'));
}
// STEP3: 使用 StreamBuilder 构建小部件
class BuildWithSocketStream extends StatelessWidget {
const BuildWithSocketStream({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: StreamBuilder(
stream: streamSocket.getResponse,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
return Container(
child: snapshot.hasData ? Text(snapshot.data) : Text('No data'),
);
},
),
);
}
}
故障排除
无法连接 “https” 服务器或自签名证书服务器
有关详细信息,请参阅 此问题。
解决方法是使用由 @lehno 提供的以下代码:
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext context) {
return super.createHttpClient(context)
..badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
}
}
void main() {
HttpOverrides.global = MyHttpOverrides();
runApp(MyApp());
}
iOS 关闭套接字时的内存泄漏问题
有关详细信息,请参阅 此问题。
请使用 socket.dispose()
代替 socket.close()
或 socket.disconnect()
来解决 iOS 上的内存泄漏问题。
macOS 上出现 Connect_error 错误
有关详细信息,请参阅 此问题。
通过将以下键添加到 *.entitlements
文件中来解决问题:
<key>com.apple.security.network.client</key>
<true/>
更多关于Flutter实时通信插件socket_io_client_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter实时通信插件socket_io_client_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个使用 socket_io_client_flutter
插件在 Flutter 中实现实时通信的示例代码。这个示例展示了如何连接到 Socket.IO 服务器、发送和接收消息。
首先,确保你已经在 pubspec.yaml
文件中添加了 socket_io_client_flutter
依赖:
dependencies:
flutter:
sdk: flutter
socket_io_client_flutter: ^2.0.0-beta.4-nullsafety.0 # 请根据需要检查最新版本
然后运行 flutter pub get
以获取依赖。
接下来,在你的 Flutter 项目中创建一个简单的实时通信示例。
main.dart
import 'package:flutter/material.dart';
import 'package:socket_io_client_flutter/socket_io_client.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Socket.IO Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SocketIODemo(),
);
}
}
class SocketIODemo extends StatefulWidget {
@override
_SocketIODemoState createState() => _SocketIODemoState();
}
class _SocketIODemoState extends State<SocketIODemo> {
late SocketIO socket;
final TextEditingController _messageController = TextEditingController();
final List<String> _messages = [];
@override
void initState() {
super.initState();
initSocket();
}
void initSocket() {
socket = io('http://your-socket-io-server-url:port', <String, dynamic>{
'transports': ['websocket'],
});
socket.onConnect((_) {
print('Connected to server');
_messages.add('Connected to server');
setState(() {});
});
socket.onDisconnect((_) {
print('Disconnected from server');
_messages.add('Disconnected from server');
setState(() {});
});
socket.onMessage((data) {
print('Message from server: $data');
_messages.add('Server: $data');
setState(() {});
});
socket.onError((error) {
print('Error: $error');
_messages.add('Error: $error');
setState(() {});
});
}
void _sendMessage() {
if (_messageController.text.isNotEmpty) {
socket.emit('message', _messageController.text);
_messages.add('You: ${_messageController.text}');
_messageController.clear();
setState(() {});
}
}
@override
void dispose() {
socket.disconnect();
_messageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Socket.IO Demo'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: _messages.length,
itemBuilder: (_, index) {
return Text(_messages[index], style: TextStyle(fontSize: 18));
},
),
),
TextField(
controller: _messageController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Enter message',
),
onSubmitted: _sendMessage,
),
ElevatedButton(
onPressed: _sendMessage,
child: Text('Send'),
),
],
),
),
);
}
}
说明
-
连接到 Socket.IO 服务器:
- 使用
io('http://your-socket-io-server-url:port', options)
方法连接到 Socket.IO 服务器。 options
参数允许你配置传输方式等。在这个示例中,我们只指定了transports: ['websocket']
。
- 使用
-
事件监听:
socket.onConnect
:当连接到服务器时触发。socket.onDisconnect
:当从服务器断开连接时触发。socket.onMessage
:当从服务器接收到消息时触发。socket.onError
:当发生错误时触发。
-
发送消息:
- 使用
socket.emit('event', data)
方法发送消息。在这个示例中,我们发送一个名为message
的事件,数据为输入框中的内容。
- 使用
-
UI:
- 使用
ListView.builder
显示消息历史。 - 使用
TextField
和ElevatedButton
发送消息。
- 使用
请确保将 'http://your-socket-io-server-url:port'
替换为你的 Socket.IO 服务器的实际 URL 和端口。
这个示例展示了基本的实时通信功能。你可以根据需要扩展这个示例,例如处理更多的事件、增加错误处理等。