Flutter WebSocket通信插件web_socket_support的使用
Flutter WebSocket通信插件web_socket_support的使用
插件介绍
web_socket_support
是一个用于在 Android 平台上实现 WebSocket 通信的 Flutter 插件。该插件基于 OkHttp 实现,旨在解决标准 Flutter WebSocket 实现中的一些问题,如屏幕锁定或应用后台时连接断开的问题。
使用示例
下面是一个完整的示例代码,展示了如何使用 web_socket_support
插件进行 WebSocket 通信。
import 'package:flutter/material.dart';
import 'package:web_socket_support/web_socket_support.dart';
void main() async {
final backend = WsBackend();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<WsBackend>.value(
value: backend,
),
ChangeNotifierProvider<WebSocketSupport>(
create: (ctx) => WebSocketSupport(backend),
),
],
child: const WebSocketSupportExampleApp(),
),
);
}
class WsBackend with ChangeNotifier {
final textController = TextEditingController();
final List<ServerMessage> _messages = [];
WsBackend() {
print('WsBackend created.');
}
void addMessage(ServerMessage msg) {
_messages.add(msg);
notifyListeners();
}
void clearMessages() {
_messages.clear();
notifyListeners();
}
List<ServerMessage> getMessages() {
return List.unmodifiable(_messages);
}
bool hasMessages() {
return _messages.isNotEmpty;
}
[@override](/user/override)
void dispose() {
textController.dispose();
super.dispose();
}
}
class WebSocketSupport with ChangeNotifier {
static const String serverUrl = 'ws://ws.ifelse.io';
final WsBackend _backend;
// locals
late WebSocketClient _wsClient;
WebSocketConnection? _webSocketConnection;
bool working = false;
WebSocketSupport(this._backend) {
_wsClient = WebSocketClient(DefaultWebSocketListener.forTextMessages(
_onWsOpened,
_onWsClosed,
_onTextMessage,
(_, __) => {},
_onError,
));
print('WebSocketSupport created.');
}
void _onWsOpened(WebSocketConnection webSocketConnection) {
_webSocketConnection = webSocketConnection;
working = false;
notifyListeners();
}
void _onWsClosed(int code, String reason) {
_webSocketConnection = null;
_backend.clearMessages();
working = false;
notifyListeners();
}
void _onTextMessage(String message) {
_backend.addMessage(ServerMessage(message, DateTime.now()));
notifyListeners();
}
void _onError(Exception ex) {
print('_onError: Fatal error occurred: $ex');
_webSocketConnection = null;
working = false;
_backend.addMessage(
ServerMessage('Error occurred on WS connection!', DateTime.now()));
notifyListeners();
}
bool isConnected() {
return _webSocketConnection != null;
}
void sendMessage() {
if (_webSocketConnection != null) {
_webSocketConnection?.sendStringMessage(_backend.textController.text);
_backend.textController.clear();
}
}
Future<void> connect() async {
working = true;
_backend.textController.clear();
_backend.clearMessages();
try {
await _wsClient.connect(serverUrl,
options: WebSocketOptions(autoReconnect: true));
notifyListeners();
} on PlatformException catch (e) {
final errorMsg = 'Failed to connect to ws server. Error:$e';
print(errorMsg);
_backend.addMessage(ServerMessage(errorMsg, DateTime.now()));
}
}
Future<void> disconnect() async {
working = true;
await _wsClient.disconnect();
notifyListeners();
}
}
class WebSocketSupportExampleApp extends StatelessWidget {
const WebSocketSupportExampleApp({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('WebSocketSupport example app'),
),
body: const Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
WsControlPanel(),
WsTextInput(),
WsMessages(),
],
),
),
);
}
}
class WsControlPanel extends StatelessWidget {
const WsControlPanel({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return Column(
children: [
const SizedBox(height: 10),
Center(
child: Consumer<WebSocketSupport>((
builder: (ctx, ws, _) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: Row(
children: [
// status title
const Text('WS status:'),
Padding(
padding: const EdgeInsets.only(left: 5, right: 5),
child: Icon(
ws.isConnected()
? Icons.check_circle_outlined
: Icons.highlight_off,
color: _connectionColor(ws),
size: 20,
),
),
// status value
Text(
(ws.isConnected() ? 'Connected' : 'Disconnected'),
style: TextStyle(color: _connectionColor(ws)),
),
],
),
),
Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: ElevatedButton(
key: const Key('connect'),
onPressed: ws.working
? null
: () async {
ws.isConnected()
? await ws.disconnect()
: await ws.connect();
},
child: ws.isConnected()
? const Text('Disconnect')
: const Text('Connect'),
),
),
],
);
},
),
),
const Divider(),
],
);
}
MaterialColor _connectionColor(WebSocketSupport ws) =>
ws.isConnected() ? Colors.green : Colors.red;
}
class WsTextInput extends StatelessWidget {
const WsTextInput({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return Consumer<WebSocketSupport>(builder: (ctx, ws, _) {
return !ws.isConnected()
? const SizedBox.shrink()
: Column(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Row(
children: [
Expanded(
child: TextField(
key: const Key('textField'),
textAlign: TextAlign.center,
controller:
Provider.of<WsBackend>(context, listen: false)
.textController,
decoration: const InputDecoration(
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.greenAccent, width: 2.0),
),
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.blue, width: 2.0),
),
hintText: 'Enter message to send to server',
),
),
),
IconButton(
key: const Key('sendButton'),
icon: const Icon(Icons.send),
onPressed: () => ws.sendMessage(),
),
],
),
),
const Divider(),
],
);
});
}
}
class WsMessages extends StatelessWidget {
const WsMessages({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return Consumer<WsBackend>((
builder: (ctx, be, _) {
return be.getMessages().isEmpty
? const SizedBox.shrink()
: Expanded(
child: Column(
children: [
const Padding(
padding: EdgeInsets.only(top: 10, bottom: 10),
child: Text(
'Reply messages from: ${WebSocketSupport.serverUrl}',
key: Key('replyHeader'),
),
),
Expanded(
child: ListView.separated(
itemCount: be.getMessages().length,
separatorBuilder: (BuildContext context, int index) =>
const Divider(),
itemBuilder: (BuildContext context, int index) {
var message = be.getMessages()[index];
return ListTile(
title: Text(
'${DateFormat.Hms().format(message.dateTime)}: ${message.message}',
key: Key(message.message),
),
);
},
),
),
],
),
);
});
}
}
class ServerMessage {
final String message;
final DateTime dateTime;
ServerMessage(this.message, this.dateTime);
}
更多关于Flutter WebSocket通信插件web_socket_support的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter WebSocket通信插件web_socket_support的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 web_socket_support
插件在 Flutter 中实现 WebSocket 通信的示例代码。需要注意的是,web_socket_support
并不是一个官方或者广泛使用的 Flutter 插件名称,通常 Flutter 开发者会使用 web_socket_channel
插件来进行 WebSocket 通信。不过,为了符合你的要求,我将假设 web_socket_support
提供了类似的功能,并给出相应的示例代码。
在实际开发中,如果 web_socket_support
插件存在并且功能类似 web_socket_channel
,你应该参考该插件的官方文档进行调整。以下示例基于假设的 web_socket_support
插件提供了与 web_socket_channel
类似的功能。
示例代码
- 添加依赖
首先,在你的 pubspec.yaml
文件中添加 web_socket_support
依赖(假设存在):
dependencies:
flutter:
sdk: flutter
web_socket_support: ^x.y.z # 替换为实际的版本号
然后运行 flutter pub get
来获取依赖。
- 实现 WebSocket 通信
接下来,在你的 Flutter 应用中实现 WebSocket 通信。以下是一个简单的示例,展示如何连接到 WebSocket 服务器、发送消息和接收消息。
import 'package:flutter/material.dart';
import 'package:web_socket_support/web_socket_support.dart'; // 假设包名和导入路径
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'WebSocket Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: WebSocketPage(),
);
}
}
class WebSocketPage extends StatefulWidget {
@override
_WebSocketPageState createState() => _WebSocketPageState();
}
class _WebSocketPageState extends State<WebSocketPage> {
WebSocketChannel? _channel;
TextEditingController _controller = TextEditingController();
List<String> _messages = [];
@override
void initState() {
super.initState();
connectToWebSocket();
}
void connectToWebSocket() {
_channel = WebSocketChannel.connect(Uri.parse('ws://your-websocket-server-url'));
_channel!.stream.listen(
(message) {
setState(() {
_messages.add('Received: $message');
});
},
onError: (error) {
setState(() {
_messages.add('Error: ${error.message}');
});
},
onDone: () {
setState(() {
_messages.add('WebSocket connection closed.');
});
},
);
}
void sendMessage() {
if (_controller.text.isNotEmpty) {
_channel!.sink.add(_controller.text);
setState(() {
_messages.add('Sent: ${_controller.text}');
_controller.clear();
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('WebSocket 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: _controller,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Enter message',
),
onSubmitted: (value) {
sendMessage();
},
),
ElevatedButton(
onPressed: sendMessage,
child: Text('Send'),
),
],
),
),
);
}
@override
void dispose() {
_channel?.sink.close();
_controller.dispose();
super.dispose();
}
}
注意事项
- 替换 WebSocket 服务器 URL:将
ws://your-websocket-server-url
替换为你实际的 WebSocket 服务器 URL。 - 错误处理:在实际应用中,你可能需要更完善的错误处理和重连机制。
- 插件文档:由于
web_socket_support
是一个假设的插件名称,请参考实际使用的插件文档以获取更多信息和最佳实践。
如果 web_socket_support
实际上并不存在或者功能不同,你可能需要使用 web_socket_channel
或其他类似的插件,并参考其官方文档进行实现。