Flutter实时通信插件x_action_cable的使用
Flutter实时通信插件x_action_cable的使用
ActionCable 是 Rails 默认的实时 WebSocket 框架和协议。
这个库是 ActionCable 的 Dart 端口,适用于 Web、DartVM 和 Flutter。它与其他库的主要区别在于它使用的某些模式。例如,服务器的响应需要符合我们期望的格式,并且会根据最新的 Dart 特性来改进代码(我知道我们仍然有一些代码需要改进)。更多细节见下文。
使用方法
连接到 WebSocket
final cable = ActionCable.connect(
'ws://127.0.0.1:3000/cable',
headers: {
'Authorization': 'jwt-token',
},
onConnected: () {
print('connected');
},
onConnectionLost: () {
print('connection lost');
},
onCannotConnect: () {
print('cannot connect');
},
);
订阅频道
void receiveMessage(Map payload) => print(payload);
final actionCallback = ActionCallback(name: 'on_receive_message', callback: receiveMessage);
ActionChannel channel = cable.subscribe(
'Chat', // 可以是 'Chat' 或 'ChatChannel'
channelParams: { 'room': 'private' },
onSubscribed: () {}, // 收到 'confirm_subscription' 后调用
onDisconnected: () {}, // 收到 'disconnect' 后调用
callbacks: [actionCallback], // 服务器可以调用的所有回调列表
);
当服务器发送带有键 ‘on_receive_message’ 的数据时,库将能够识别并正确调用回调。
例如,服务器需要发送的数据如下:
ActionCable.server.broadcast("notifications_#{current_user}", {method: "on_receive_message", data: { anyData: [1, 2, 3] }})
上面的第二个参数是键 ‘method’,这是库在客户端侧调用回调所需的所有信息。
通过这个 ActionChannel,你还可以从通道对象执行操作。更多信息见下文。
取消订阅频道
首先,让我们看看如何取消订阅频道。记住你创建的 ActionChannel 对象,你将使用相同的对象来取消订阅。
channel.unsubscribe();
就这样,不需要更多的步骤。现在让我们看看如何从客户端向服务器发起操作。
在你的 ActionCable 服务器上执行操作
再次,记住你之前创建的对象?就是通道对象。我们将使用它来执行一个操作。
channel.performAction(
action: 'send_message',
actionParams: { 'message': 'Hello private peeps! 😜' }
);
这里有一些其他参数。
- action: 你要调用的服务器端方法的名称。
- actionParams: 传递给服务器的参数。
下面是一个 Ruby on Rails 方法的例子:
def send_message(data)
puts("message: #{data}")
end
断开与 ActionCable 服务器的连接
最后,断开连接时,你需要使用主对象(ActionCable)来断开 WebSocket。
cable.disconnect();
ActionCable 协议
Anycable 在该主题上有非常好的文档。
贡献者 ✨
该项目遵循 all-contributors 规范。欢迎任何形式的贡献!
示例代码
下面是完整的示例代码:
import 'package:flutter/material.dart';
import 'package:x_action_cable/x_action_cable.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Example',
theme: ThemeData(primarySwatch: Colors.blue),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
[@override](/user/override)
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late final ActionCable cable;
late final ActionChannel channel;
[@override](/user/override)
void initState() {
super.initState();
// 连接到 WebSocket
cable = ActionCable.connect(
'ws://chat.example.com/cable',
headers: {'Authorization': 'Some Token'},
onConnected: onConnected,
onConnectionLost: onConnectionLost,
onCannotConnect: onCannotConnect,
);
// 订阅频道以接收服务器消息
// 参数 callbacks 是所有服务器可以在前端应用中调用的方法
// 首先你需要定义一个 ActionCallback
// 参数 name 是服务器将调用的名称
// 参数 callback 是基于名称调用的方法
// 如果服务器发送带有参数 "method": "on_receive_message" 的消息,
// 库将为你调用 onReceiveMessage。
// 库期望服务器发送的数据格式为:{"method": "on_receive_message", "data": "任何消息"}
final onMessageCallback = ActionCallback(
name: 'on_receive_message',
callback: onReceiveMessage,
);
channel = cable.subscribe(
'Chat',
onSubscribed: onChannelSubscribed,
callbacks: [onMessageCallback],
);
}
void onConnected() => debugPrint('connected');
void onConnectionLost() => debugPrint('connection lost');
void onCannotConnect(dynamic reason) => debugPrint(reason.toString());
void onChannelSubscribed() {
debugPrint('Subscribed to the ChatChannel');
// 订阅频道后,你可以开始向其发送动作
// 第一个参数是要调用的服务器端方法的名称
// 参数 [params] 是要发送给服务器的数据
channel.performAction(
'send_message',
params: {'message': 'Hello World'},
);
}
void onReceiveMessage(ActionResponse response) {
final message = response.data ?? response.error;
debugPrint('$message');
}
[@override](/user/override)
void dispose() {
// 最后,你可以断开所有通道
channel.unsubscribe();
// 当你断开 WebSocket 连接时,cable 会自动断开连接
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text(
'Example showing how the lib works!\nCurrently we don\'t have any server to supply the example. Be patient',
),
),
);
}
}
更多关于Flutter实时通信插件x_action_cable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter实时通信插件x_action_cable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter应用中使用x_action_cable
插件来实现实时通信的一个基本示例。x_action_cable
插件通常用于与Rails的Action Cable进行集成,以实现WebSocket通信。
首先,确保你已经在你的Flutter项目中添加了x_action_cable
依赖。你可以在你的pubspec.yaml
文件中添加以下依赖项:
dependencies:
flutter:
sdk: flutter
x_action_cable: ^最新版本号 # 请替换为实际的最新版本号
然后运行flutter pub get
来安装依赖。
配置Action Cable服务器
假设你已经在Rails中配置好了Action Cable,并且有一个名为ChatChannel
的通道,你可以发送和接收消息。
Flutter 客户端代码
以下是一个简单的Flutter应用,展示如何使用x_action_cable
插件连接到Action Cable服务器,并发送和接收消息。
-
创建一个新的Flutter项目(如果你还没有的话):
flutter create my_flutter_app cd my_flutter_app
-
修改
pubspec.yaml
(如上所述)。 -
编写Flutter代码:
// main.dart import 'package:flutter/material.dart'; import 'package:x_action_cable/x_action_cable.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Action Cable Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: ChatScreen(), ); } } class ChatScreen extends StatefulWidget { @override _ChatScreenState createState() => _ChatScreenState(); } class _ChatScreenState extends State<ChatScreen> { final TextEditingController _messageController = TextEditingController(); final List<String> _messages = []; ActionCableClient? _cableClient; @override void initState() { super.initState(); connectToActionCable(); } void connectToActionCable() async { // 替换为你的Action Cable服务器URL和通道名称 String url = 'wss://your-rails-app-url/cable'; String channel = 'ChatChannel'; _cableClient = await ActionCableClient.connect(url); _cableClient!.subscribe( channel, params: {'room': 'general'}, // 传递任何需要的参数 onReceived: (data) { // 处理接收到的消息 setState(() { _messages.add(data['message']); }); }, onConnected: () { print('Connected to Action Cable'); }, onDisconnected: () { print('Disconnected from Action Cable'); }, ); } void sendMessage() { if (_messageController.text.isNotEmpty) { _cableClient?.perform( channel: 'ChatChannel', action: 'speak', data: {'message': _messageController.text}, ); setState(() { _messages.add('You: $_messageController.text'); _messageController.clear(); }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Flutter Action Cable Chat'), ), body: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: <Widget>[ Expanded( child: ListView.builder( itemCount: _messages.length, itemBuilder: (context, index) { return ListTile( title: Text(_messages[index]), ); }, ), ), TextField( controller: _messageController, onSubmitted: sendMessage, decoration: InputDecoration( border: OutlineInputBorder(), labelText: 'Message', suffixIcon: IconButton( icon: Icon(Icons.send), onPressed: sendMessage, ), ), ), ], ), ), ); } @override void dispose() { _cableClient?.disconnect(); _messageController.dispose(); super.dispose(); } }
解释
-
连接Action Cable:
- 使用
ActionCableClient.connect(url)
连接到Action Cable服务器。 - 使用
_cableClient!.subscribe
订阅通道,并处理接收到的消息。
- 使用
-
发送消息:
- 使用
_cableClient?.perform
发送消息到服务器。
- 使用
-
UI:
- 使用
ListView.builder
显示聊天记录。 - 使用
TextField
和IconButton
发送消息。
- 使用
确保你的Rails服务器正在运行,并且Action Cable配置正确。运行Flutter应用,你应该能够连接到服务器,发送和接收消息。