Flutter 单例封装web_socket_channel长连接,结合 event_bus 实现页面交互。

该博客介绍了如何在APP中实现长连接功能,利用WebSocket进行实时接单和通知接收。通过`web_socket_channel`库创建WebSocket连接,并使用`event_bus`进行页面交互。当连接断开或出现错误时,会进行相应的处理。此外,还设置了心跳机制以保持连接活跃。在用户登录状态改变时,会触发相应的事件。初始化和销毁Socket连接的代码示例也一并提供。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. app 需要实现长连接功能,方便实时接单和接收一些通知之类的消息。
    dependencies:
      web_socket_channel: ^2.1.0
  2. 通过eventbus 发送通知与页面交互。
    dependencies:
      event_bus: ^2.0.0
  3. socket 单例封装
    import 'dart:async';
    
    import 'package:pinmancheapp/network/url_path.dart';
    import 'package:pinmancheapp/utils/eventbus_util.dart';
    import 'package:pinmancheapp/utils/sp_utils.dart';
    import 'package:web_socket_channel/io.dart';
    
    import 'colors.dart';
    import 'dart:convert' as convert;
    
    class SocketUtils {
      SocketUtils._internal() {}
      static SocketUtils _socketUtils = SocketUtils._internal();
      IOWebSocketChannel _channel;
      Timer _timer;
    
      factory SocketUtils() {
        return _socketUtils;
      }
      
      void initSocket() {
        _channel = IOWebSocketChannel.connect(Uri.parse(UrlPath.baseSocketUrl));
        Map<String, dynamic> params = Map<String, dynamic>();
        params["userId"] = SpUtils().getUserInfo().appUserDetailsVO.drvId;
        params["userName"] = SpUtils().getUserInfo().appUserDetailsVO.drvName;
        params["token"] = SpUtils().getUserInfo().token;
        _channel.sink.add(convert.jsonEncode(params));
        _channel.stream.listen(this.onData, onError: onError, onDone: onDone);
        startCountdownTimer();
      }
    
      ///开启心跳
      void startCountdownTimer() {
        const oneSec = const Duration(seconds: 10);
        var callback = (timer) {
          if (_channel == null) {
            initSocket();
          } else {
            if(SpUtils().getUserInfo() != null){
              _channel.sink
                  .add("10002${SpUtils().getUserInfo().appUserDetailsVO.drvId}");
            }
          }
        };
        _timer = Timer.periodic(oneSec, callback);
      }
    
      onDone() {
        print("消息关闭");
        if (_channel != null) {
          _channel.sink.close();
          _channel = null;
        }
      }
    
      onError(err) {
        print("消息错误${err}");
        if (_channel != null) {
          _channel.sink.close();
          _channel = null;
        }
      }
    
      onData(event) {
        try {
          if (event != null) {
            switch (event) {
              case "10001"://服务器回应正常
              case "10002":
                break;
              case "10005":
                this.dispose();
                EventBusUtil.getInstance()
                    .fire(PageEvent(eventType: EventBusUtil.UNAUTHORIZED, data: "已在其他设备上登录\n请重新登录"));
                break;
              default:
                event = convert.jsonDecode(event);
                switch (event["msgtype"]) {//消息类型
                  case 10006:
                    //新的通知消息
                    EventBusUtil.getInstance().fire(
                        PageEvent(eventType: EventBusUtil.NEWMESSAGE));
                    break;
    
                  case 20012:
                    //通知刷新列表
                    EventBusUtil.getInstance()
                        .fire(PageEvent(eventType: EventBusUtil.REFRESHORDERLIST));
                    break;
                  case 20014:
                    ///有新订单
                    EventBusUtil.getInstance()
                        .fire(PageEvent(eventType: EventBusUtil.NEWORDERMESSAGE));
                    break;
                }
            }
          }
        } catch (e) {
          print(e);
        }
      }
    
      void dispose() {
        if (_channel != null) {
          _channel.sink.close();
          print("socket通道关闭");
          _channel = null;
        }
        if (_timer != null) {
          _timer.cancel();
          _timer = null;
        }
      }
    }
    
  4. 在合适的地方调用,销毁
     

      /// 初始化 socket链接
      SocketUtils().initSocket();
    
      /// 销毁后的一些处理
      SocketUtils().dispose();

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值