文章将介绍如何对
web_socket_channel
进行通用封装
引入插件
pubspec.yaml
web_socket_channel: ^1.2.0
插件封装
hi_socket.dart
封装思想:针对 websocket 插件提供的功能,进行抽象层的提取封装,从建立连接、和服务端通信(发送、接收)、以及通信中的异常处理、还有关闭连接等功能
class HiSocket extends ISocket {
final Map<String, dynamic> headers;
static const _URL = "wss://api.devio.org/uapi/fa/barrage/";
ValueChanged<List<BarrageModel>> _callBack;
IOWebSocketChannel _channel;
/// 心跳间隔秒数,根据服务器实际timeout时间来调整,这里Nginx服务器的timeout为60
int _intervalSeconds = 50;
HiSocket(this.headers);
/// 关闭连接
@override
void close() {
_channel?.sink?.close();
}
/// 监听服务端返回的数据
@override
ISocket listen(ValueChanged<List<BarrageModel>> _callBack) {
_callBack = _callBack;
return this;
}
/// 建立连接
@override
ISocket open(String vid) {
_channel = IOWebSocketChannel.connect(_URL + vid,
headers: headers, pingInterval: Duration(seconds: _intervalSeconds));
_channel.stream.handleError((error) {
print('连接发生错误:$error');
}).listen((message) {
// 监听服务端返回的消息
_handleMessage(message);
});
return this;
}
/// 向服务端发送消息
@override
ISocket send(String message) {
_channel?.sink?.add(message);
return this;
}
/// 处理从服务端返回的消息
void _handleMessage(message) {
var result = BarrageModel.fromJson(message);
if (result != null && _callBack != null) {
_callBack(message);
}
}
}
/// 抽象层封装:提取通用socket 功能
abstract class ISocket {
/// 建立连接
/// vid: 视频ID,返回 ISocket 是为了链式调用
ISocket open(String vid);
/// 发送弹幕
ISocket send(String message);
/// 接收数据
ISocket listen(ValueChanged<List<BarrageModel>> _callBack);
/// 关闭连接
void close();
}
如何使用
HiSocket _hiSocket;
@override
void initState() {
super.initState();
_initSocket();
}
@override
void dispose() {
// 关闭socket
_hiSocket.close();
super.dispose();
}
/// 初始化HiSocket
void _initSocket() {
_hiSocket = HiSocket(HiConstants.headers());
// 监听从服务端返回的消息
_hiSocket.open(videoModel.vid).listen((value) {
print('收到:$value');
});
}
}
hi_constants.dart
和服务端通信鉴权的信息,一般都封装到每一次http请求的 header 中
class HiConstants {
static String authTokenK = "auth-token";
static String authTokenV = "ZmEtMjAyMS0wNC0xMiAyMToyMjoyMC1mYQ==fa";
static String courseFlagK = "course-flag";
static String courseFlagV = "fa";
static const theme = "hi_theme";
/// 设置请求头校验,注意留意:Console的log输出:flutter: received:
static headers() {
Map<String, dynamic> header = {
HiConstants.authTokenK: HiConstants.authTokenV,
HiConstants.courseFlagK: HiConstants.courseFlagV
};
var boardingPass = LoginDao.getBoardingPass();
if (boardingPass != null) {
header[LoginDao.BOARDING_PASS] = boardingPass;
}
return header;
}
}