Flutter实时通信插件netcore_signalr的使用
Flutter实时通信插件netcore_signalr的使用
简介
signalr_netcore
是一个用于 Flutter 应用程序的 ASP.NET Core SignalR 客户端库。ASP.NET Core SignalR 是一个开源库,它简化了向应用程序添加实时Web功能的过程。实时Web功能使服务器端代码能够即时推送内容到客户端。
本库经过测试,支持 ASP.NET Core 3.1 和 ASP.NET Core 6。该客户端能够调用服务器端的Hub函数(包括流式函数)并接收由服务器发起的方法调用。它还支持自动重连功能。
该客户端支持以下传输协议:
- WebSocket
- Service Side Events
- Long Polling
该客户端支持以下Hub协议:
- Json
- MessagePack
示例
聊天客户端/服务器
开始使用
在 pubspec.yaml
文件中添加 signalr_netcore
依赖项:
dependencies:
flutter:
sdk: flutter
signalr_netcore:
重要提示:如果你遇到问题(例如未接收到消息回调),请尝试使用旧版本,如 signalr_netcore: 0.1.7+2-nullsafety.3
,但请注意,该版本不支持自动重连功能,需要手动处理。
使用方法
以下是一些基本用法的示例:
1. 创建Hub连接
// 导入库
import 'package:signalr_netcore/signalr_client.dart';
// 服务器地址
final serverUrl = "192.168.10.50:51001";
// 创建连接
final hubConnection = HubConnectionBuilder().withUrl(serverUrl).build();
// 连接关闭时打印消息
hubConnection.onclose((error) => print("Connection Closed"));
日志记录可以通过 logging
包进行配置:
// 导入库
import 'package:logging/logging.dart';
import 'package:signalr_netcore/signalr_client.dart';
// 配置日志
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((LogRecord rec) {
print('${rec.level.name}: ${rec.time}: ${rec.message}');
});
// 日志记录级别为Hub协议
final hubProtLogger = Logger("SignalR - hub");
// 日志记录级别为传输
final transportProtLogger = Logger("SignalR - transport");
// 创建带有日志记录选项的连接
final httpOptions = HttpConnectionOptions(logger: transportProtLogger);
final hubConnection = HubConnectionBuilder().withUrl(serverUrl, options: httpOptions).configureLogging(hubProtLogger).build();
// 连接关闭时打印消息
hubConnection.onclose((error) => print("Connection Closed"));
2. 连接到Hub
调用以下方法开始握手并连接客户端到SignalR服务器:
await hubConnection.start();
3. 调用Hub函数
假设有一个Hub函数:
public string MethodOneSimpleParameterSimpleReturnValue(string p1)
{
Console.WriteLine($"'MethodOneSimpleParameterSimpleReturnValue' invoked. Parameter value: '{p1}");
return p1;
}
客户端可以调用此函数:
final result = await hubConnection.invoke("MethodOneSimpleParameterSimpleReturnValue", args: <Object>["ParameterValue"]);
logger.log(LogLevel.Information, "Result: '$result'");
4. 调用客户端函数
假设服务器调用名为 “aClientProvidedFunction” 的函数:
await Clients.Caller.SendAsync("aClientProvidedFunction", null);
客户端可以这样实现:
hubConnection.on("aClientProvidedFunction", _handleAClientProvidedFunction);
// 取消注册函数
// a) 取消注册特定实现
// hubConnection.off("aClientProvidedFunction", method: _handleServerInvokeMethodNoParametersNoReturnValue);
// b) 取消注册所有实现
// hubConnection.off("aClientProvidedFunction");
void _handleAClientProvidedFunction(List<Object> parameters) {
logger.log(LogLevel.Information, "Server invoked the method");
}
5. 使用Msgpack进行序列化
如果需要使用Msgpack协议进行序列化,需要在客户端和服务器上都进行配置。
客户端
import 'package:signalr_netcore/msgpack_hub_protocol.dart';
_hubConnection = HubConnectionBuilder()
.withUrl(_serverUrl, options: httpOptions)
/* 配置Hub使用Msgpack协议 */
.withHubProtocol(MessagePackHubProtocol())
.withAutomaticReconnect()
.configureLogging(logger)
.build();
服务器
在ASP.NET Core项目中添加以下包:
Microsoft.AspNetCore.SignalR.Protocols.MessagePack
然后在 ConfigureServices
方法中配置Hub使用Msgpack协议:
public void ConfigureServices(IServiceCollection services)
{
// 配置Hub使用Msgpack协议
services.AddSignalR().AddMessagePackProtocol();
}
参数类型注意事项
所有函数参数和返回值都通过 dart:convert
包(json.encode/json.decode)进行序列化/反序列化。确保你:
- 只使用简单参数类型
- 或者使用实现了
toJson()
方法的对象,因为该方法被dart:convert
包用来序列化对象。
如何暴露MessageHeaders对象以便客户端发送默认头
final defaultHeaders = MessageHeaders();
defaultHeaders.setHeaderValue("HEADER_MOCK_1", "HEADER_VALUE_1");
defaultHeaders.setHeaderValue("HEADER_MOCK_2", "HEADER_VALUE_2");
final httpConnectionOptions = HttpConnectionOptions(
httpClient: WebSupportingHttpClient(logger, httpClientCreateCallback: _httpClientCreateCallback),
accessTokenFactory: () => Future.value('JWT_TOKEN'),
logger: logger,
logMessageContent: true,
headers: defaultHeaders);
final _hubConnection = HubConnectionBuilder()
.withUrl(_serverUrl, options: httpConnectionOptions)
.withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000, null])
.configureLogging(logger)
.build();
HTTP请求日志:
I/flutter ( 5248): Starting connection with transfer format 'TransferFormat.Text'.
I/flutter ( 5248): Sending negotiation request: https://localhost:5000/negotiate?negotiateVersion=1
I/flutter ( 5248): HTTP send: url 'https://localhost:5000/negotiate?negotiateVersion=1', method: 'POST' content: '' content length = '0'
headers: '{ content-type: text/plain;charset=UTF-8 }, { HEADER_MOCK_1: HEADER_VALUE_1 }, { X-Requested-With: FlutterHttpClient }, { HEADER_MOCK_2: HEADER_VALUE_2 }, { Authorization: Bearer JWT_TOKEN }'
示例代码
聊天客户端/服务器
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return const Placeholder();
}
}
更多关于Flutter实时通信插件netcore_signalr的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter实时通信插件netcore_signalr的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个使用Flutter和netcore_signalr
插件实现实时通信的示例代码。这个示例假设你已经有一个ASP.NET Core SignalR服务器在运行,并且你希望从Flutter客户端连接到该服务器并接收实时消息。
1. 设置Flutter项目
首先,确保你已经创建了一个Flutter项目。如果还没有,可以使用以下命令创建:
flutter create signalr_flutter_app
cd signalr_flutter_app
2. 添加netcore_signalr
依赖
在你的pubspec.yaml
文件中添加netcore_signalr
依赖:
dependencies:
flutter:
sdk: flutter
netcore_signalr: ^最新版本号 # 请替换为实际的最新版本号
然后运行flutter pub get
来安装依赖。
3. 配置SignalR客户端
在你的lib
目录下,打开main.dart
文件,并进行如下修改:
import 'package:flutter/material.dart';
import 'package:netcore_signalr/netcore_signalr.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter SignalR Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SignalRScreen(),
);
}
}
class SignalRScreen extends StatefulWidget {
@override
_SignalRScreenState createState() => _SignalRScreenState();
}
class _SignalRScreenState extends State<SignalRScreen> {
late SignalRHubConnection _connection;
final TextEditingController _messageController = TextEditingController();
final List<String> _messages = [];
@override
void initState() {
super.initState();
_initSignalRConnection();
}
void _initSignalRConnection() {
// 配置SignalR连接
_connection = SignalRHubConnection(
url: 'https://你的signalr服务器地址/你的hub路径', // 替换为你的SignalR服务器URL
);
// 监听接收到的消息
_connection.on('ReceiveMessage', (arguments) {
setState(() {
_messages.add(arguments['message']);
});
});
// 尝试连接SignalR服务器
_connection.start().then((_) {
print('Connected to SignalR server');
}).catchError((error) {
print('Failed to connect to SignalR server: $error');
});
}
void _sendMessage() {
final message = _messageController.text;
if (message.isNotEmpty) {
// 发送消息到SignalR服务器
_connection.invoke('SendMessage', {'message': message}).then((_) {
setState(() {
_messageController.clear();
_messages.add('You: $message');
});
}).catchError((error) {
print('Failed to send message: $error');
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter SignalR Demo'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: _messages.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_messages[index]),
);
},
),
),
TextField(
controller: _messageController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Message',
suffixIcon: IconButton(
icon: Icon(Icons.send),
onPressed: _sendMessage,
),
),
),
],
),
),
);
}
@override
void dispose() {
// 关闭SignalR连接
_connection.stop();
super.dispose();
}
}
4. 运行Flutter应用
确保你的SignalR服务器正在运行,并且URL和Hub路径配置正确。然后,你可以通过运行以下命令来启动Flutter应用:
flutter run
这个示例展示了如何使用netcore_signalr
插件在Flutter应用中实现实时通信。你可以根据需要扩展这个示例,比如处理更多类型的消息、增加错误处理等。