Flutter SignalR客户端通信插件signalr_client_core的使用
Flutter SignalR客户端通信插件signalr_client_core的使用
signalr_client
一个用于 ASP.NET Core 的 Flutter SignalR 客户端。
ASP.NET Core SignalR 是一个开源库,它简化了向应用程序添加实时 Web 功能的过程。实时 Web 功能使服务器端代码能够即时将内容推送到客户端。
测试环境:ASP.NET Core 3.1 和 ASP.NET Core 6
该客户端能够调用服务器端的 Hub 函数(包括流式函数)并接收由服务器发出的方法调用。它还支持自动重新连接功能。
该客户端支持以下传输协议:
- WebSocket
- 服务端事件
- 长轮询
该客户端支持以下 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';
// SignalR 服务器的位置。
final serverUrl = "192.168.10.50:51001";
// 使用 HubConnectionBuilder 创建连接。
final hubConnection = HubConnectionBuilder().withUrl(serverUrl).build();
// 当连接关闭时,在控制台打印一条消息。
hubConnection.onclose((error) => print("Connection Closed"));
日志记录通过 dart 的 logging 包 支持:
// 导入库。
import 'package:logging/logger.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");
// SignalR 服务器的位置。
final serverUrl = "192.168.10.50:51001";
final httpOptions = HttpConnectionOptions(logger: transportProtLogger);
//final httpOptions = new HttpConnectionOptions(logger: transportProtLogger, transport: HttpTransportType.WebSockets); // 默认传输类型。
//final httpOptions = new HttpConnectionOptions(logger: transportProtLogger, transport: HttpTransportType.ServerSentEvents);
//final httpOptions = new HttpConnectionOptions(logger: transportProtLogger, transport: HttpTransportType.LongPolling);
// 如果需要对 Hub 连接进行授权,则提供一个返回令牌字符串的异步回调函数(见 AccessTokenFactory 类型定义)并将其分配给 accessTokenFactory 参数:
// final httpOptions = new HttpConnectionOptions( .... accessTokenFactory: () async => await getAccessToken() );
// 使用 HubConnectionBuilder 创建连接。
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. 使用 MessagePack 进行序列化
Hub 应在客户端和服务器上配置为使用 MessagePack 协议
客户端
import 'package:signalr_netcore/msgpack_hub_protocol.dart';
_hubConnection = HubConnectionBuilder()
.withUrl(_serverUrl, options: httpOptions)
/* 配置 Hub 使用 MessagePack 协议 */
.withHubProtocol(MessagePackHubProtocol())
.withAutomaticReconnect()
.configureLogging(logger)
.build();
服务器
在你的 ASP.NET Core 项目中添加以下包
Microsoft.AspNetCore.SignalR.Protocols.MessagePack
public void ConfigureServices(IServiceCollection services)
{
// 配置 Hub 使用 MessagePack 协议
services.AddSignalR().AddMessagePackProtocol();
}
关于参数类型的注意事项
所有函数参数和返回值都使用 dart:convert 包(json.encode/json.decode)进行序列化/反序列化。确保你:
- 只使用简单的参数类型
- 或者
- 使用实现了
toJson()
方法的对象,因为该方法被 dart:convert 包用来序列化对象。
Flutter JSON 101:
MSGPACK
所有函数参数和返回值都使用 msgpack_dart 包进行序列化/反序列化。确保你:
- 只使用简单的参数类型
- 或者
- 使用 Json encode/decode 将类转换为 map 然后传递给 MessagePack
- 或者
- 使用自定义编码器和解码器将消息序列化为字节然后传递给 SignalR
MSGPACK - 它像 JSON 一样,但更快更小
如何暴露一个 MessageHeaders 对象以便客户端可以发送默认头
代码示例:
final defaultHeaders = MessageHeaders();
defaultHeaders.setHeaderValue("HEADER_MOCK_1", "HEADER_VALUE_1");
defaultHeaders.setHeaderValue("HEADER_MOCK_2", "HEADER_VALUE_2");
final httpConnectionOptions = new 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 'app.dart';
import 'package:flutter/material.dart';
const kChatServerUrl = "http://192.168.0.4:5000";
void main() {
runApp(App());
}
更多关于Flutter SignalR客户端通信插件signalr_client_core的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter SignalR客户端通信插件signalr_client_core的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用Flutter中的signalr_client_core
插件与SignalR服务器进行通信的代码示例。这个示例将展示如何连接到SignalR服务器、订阅服务器发送的消息以及发送消息到服务器。
首先,确保你的Flutter项目中已经添加了signalr_client_core
依赖。在你的pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
signalr_client_core: ^最新版本号 # 替换为实际的最新版本号
然后运行flutter pub get
来安装依赖。
接下来,是一个简单的Flutter应用示例,它展示了如何使用signalr_client_core
插件:
import 'package:flutter/material.dart';
import 'package:signalr_client_core/signalr_client_core.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
HubConnection? _hubConnection;
TextEditingController _messageController = TextEditingController();
List<String> _messages = [];
@override
void initState() {
super.initState();
initSignalR();
}
void initSignalR() async {
var options = HttpHubConnectionBuilderOptions()
..withUrl("https://你的signalr服务器地址/yourHubEndpoint");
_hubConnection = await HubConnectionBuilder()
.withUrl("https://你的signalr服务器地址/yourHubEndpoint", options)
.build();
_hubConnection!.onclose(() {
print("Connection closed. Trying to reconnect...");
startConnection();
});
await startConnection();
_hubConnection!.on("ReceiveMessage", (message) {
setState(() {
_messages.add(message);
});
});
}
Future<void> startConnection() async {
try {
await _hubConnection!.start();
print("Connected to SignalR server");
} catch (e) {
print("Error connecting to SignalR server: $e");
}
}
void sendMessage() async {
if (_hubConnection!.state == ConnectionState.connected) {
await _hubConnection!.invoke("SendMessage", _messageController.text);
_messageController.clear();
} else {
print("Not connected to SignalR server");
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter SignalR Client'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: _messages.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_messages[index]),
);
},
),
),
TextField(
controller: _messageController,
decoration: InputDecoration(
labelText: 'Send Message',
border: OutlineInputBorder(),
),
onSubmitted: (value) {
sendMessage();
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: sendMessage,
tooltip: 'Send message',
child: Icon(Icons.send),
),
),
);
}
@override
void dispose() {
_hubConnection?.stop();
_messageController.dispose();
super.dispose();
}
}
代码说明:
- 依赖添加:在
pubspec.yaml
文件中添加signalr_client_core
依赖。 - 状态管理:使用
StatefulWidget
来管理SignalR连接的状态和消息列表。 - 初始化SignalR连接:在
initState
方法中初始化SignalR连接,并设置重连逻辑。 - 处理消息:使用
_hubConnection!.on
方法来订阅服务器发送的消息,并更新UI。 - 发送消息:定义一个
sendMessage
方法来发送消息到服务器。 - UI布局:使用
ListView
显示接收到的消息,并使用TextField
和FloatingActionButton
来发送消息。
请注意,你需要将"https://你的signalr服务器地址/yourHubEndpoint"
替换为你实际的SignalR服务器地址和Hub端点。此外,确保你的SignalR服务器已经正确配置并运行。
这个示例提供了一个基本的框架,你可以根据需要进行扩展和修改。