解决了渲染TCP推送数据,在切换功能后不稳定问题,保证了APP端的稳定性。
This commit is contained in:
@@ -9,17 +9,21 @@ import 'package:maibu_satabot_v2/core/network/protocol_decoder.dart';
|
||||
|
||||
import '../../../../core/logging/i_logger_service.dart';
|
||||
import '../../../../core/network/net_message_dispatcher.dart';
|
||||
import '../../../../core/network/tcp/tcp_client.dart';
|
||||
import 'device_status_event.dart';
|
||||
import 'device_status_state.dart';
|
||||
|
||||
class DeviceStatusBloc extends Bloc<DeviceStatusEvent, DeviceStatusState> {
|
||||
final NetMessageDispatcher _dispatcher;
|
||||
final TcpClient tcpClient; // 🔥 新增:直接访问 TcpClient
|
||||
final ILoggerService _logger = GetIt.I<ILoggerService>();
|
||||
|
||||
// 🔥 保存订阅引用,用于管理生命周期
|
||||
StreamSubscription? _tcpSubscription;
|
||||
|
||||
DeviceStatusBloc(this._dispatcher) : super(DeviceStatusInitial()) {
|
||||
DeviceStatusBloc(this._dispatcher, {TcpClient? client})
|
||||
: tcpClient = client ?? GetIt.I<TcpClient>(),
|
||||
super(DeviceStatusInitial()) {
|
||||
// 🔥 核心改动:直接在构造函数中建立TCP监听,类似RemoteControlCubit
|
||||
_initDirectTcpListener();
|
||||
|
||||
@@ -29,7 +33,10 @@ class DeviceStatusBloc extends Bloc<DeviceStatusEvent, DeviceStatusState> {
|
||||
on<PushMessageReceived>(_handlePushMessageReceived);
|
||||
}
|
||||
|
||||
// 🔥 新增:重新初始化TCP监听器(用于页面重新进入时调用)
|
||||
// 🔥 已废弃:重新初始化TCP监听器会导致数据流中断
|
||||
// DeviceStatusBloc是单例,TCP监听器在构造函数中建立后应始终保持活跃
|
||||
// 任何页面只需通过 BlocBuilder 或 stream 订阅状态即可
|
||||
/*
|
||||
void reinitializeListener() {
|
||||
debugPrint('🔄 [DeviceStatusBloc] 重新初始化TCP监听器 - isClosed=$isClosed');
|
||||
_logger.log('🔄 [DeviceStatusBloc] 重新初始化TCP监听器 - isClosed=$isClosed');
|
||||
@@ -40,11 +47,11 @@ class DeviceStatusBloc extends Bloc<DeviceStatusEvent, DeviceStatusState> {
|
||||
return;
|
||||
}
|
||||
|
||||
// 取消旧的订阅
|
||||
// ❌ 取消旧的订阅会导致数据流中断!
|
||||
debugPrint('📝 [DeviceStatusBloc] 取消旧订阅');
|
||||
_tcpSubscription?.cancel();
|
||||
|
||||
// 重置状态为初始状态
|
||||
// ❌ 重置状态会清空UI显示的数据!
|
||||
debugPrint('📝 [DeviceStatusBloc] emit Initial状态');
|
||||
emit(DeviceStatusInitial());
|
||||
|
||||
@@ -52,16 +59,31 @@ class DeviceStatusBloc extends Bloc<DeviceStatusEvent, DeviceStatusState> {
|
||||
debugPrint('📝 [DeviceStatusBloc] 调用 _initDirectTcpListener');
|
||||
_initDirectTcpListener();
|
||||
}
|
||||
*/
|
||||
|
||||
// 🔥 新增:直接监听TCP 0x02指令,实时解析并emit状态
|
||||
void _initDirectTcpListener() {
|
||||
debugPrint('🔗 [DeviceStatusBloc] 初始化直接TCP监听器(类似RemoteControlCubit)');
|
||||
debugPrint('🔗 [DeviceStatusBloc] 初始化直接TCP监听器 - 使用 tcpClient.packetStream');
|
||||
_logger.log('🔗 [DeviceStatusBloc] 初始化直接TCP监听器');
|
||||
|
||||
_tcpSubscription = _dispatcher.onStringMessage().listen(
|
||||
(message) {
|
||||
// 🔥 关键修复:直接监听 tcpClient.packetStream,不经过 dispatcher 的 filtered stream
|
||||
// 这样即使没有其他监听者,TCP流也不会暂停
|
||||
_tcpSubscription = tcpClient.packetStream
|
||||
.where((p) => p.command == 0x02)
|
||||
.map((p) {
|
||||
try {
|
||||
final result = utf8.decode(p.payload, allowMalformed: true);
|
||||
debugPrint('✅ [DeviceStatusBloc] 收到0x02数据: $result');
|
||||
return result;
|
||||
} catch (e) {
|
||||
debugPrint('❌ [DeviceStatusBloc] 解码失败: $e');
|
||||
return '';
|
||||
}
|
||||
})
|
||||
.listen(
|
||||
(message) {
|
||||
//debugPrint('📩 [DeviceStatusBloc] 直接收到0x02数据,长度:${message.length}');
|
||||
|
||||
|
||||
if (message.isEmpty) {
|
||||
//debugPrint('⚠️ [DeviceStatusBloc] 消息为空,跳过');
|
||||
return;
|
||||
@@ -115,6 +137,7 @@ class DeviceStatusBloc extends Bloc<DeviceStatusEvent, DeviceStatusState> {
|
||||
obstacleFlag: status.obstacleFlag,
|
||||
);
|
||||
final newGps = GPSEntity(status.latitude, status.longitude);
|
||||
debugPrint('📤 [DeviceStatusBloc] emit DeviceStatusUpdated - 电压:${status.voltage}, 电量:${status.battery}, 模式:${status.controlMode}');
|
||||
emit(DeviceStatusUpdated(newStatus, newGps));
|
||||
}
|
||||
} catch (e, stack) {
|
||||
@@ -135,11 +158,12 @@ class DeviceStatusBloc extends Bloc<DeviceStatusEvent, DeviceStatusState> {
|
||||
|
||||
// 🔥 重置时仅清空状态
|
||||
Future<void> _handleReset(DeviceStatusReset event, Emitter<DeviceStatusState> emit) async {
|
||||
debugPrint('🔄 [DeviceStatusBloc] 收到重置事件:清空状态');
|
||||
_logger.log('🔄 [DeviceStatusBloc] 收到重置事件:清空状态');
|
||||
debugPrint('🔄 [DeviceStatusBloc] 收到重置事件:清空状态 - 当前状态:${state.runtimeType}');
|
||||
_logger.log('🔄 [DeviceStatusBloc] 收到重置事件:清空状态 - 当前状态:${state.runtimeType}');
|
||||
|
||||
// 只 emit 初始状态,让 UI 清除旧设备的数据
|
||||
emit(DeviceStatusInitial());
|
||||
debugPrint('⚠️ [DeviceStatusBloc] 已emit DeviceStatusInitial');
|
||||
}
|
||||
|
||||
Future<void> _handleDeviceStatusLoaded(
|
||||
@@ -189,7 +213,7 @@ class DeviceStatusBloc extends Bloc<DeviceStatusEvent, DeviceStatusState> {
|
||||
Future<void> close() {
|
||||
debugPrint('🚫 [DeviceStatusBloc] 页面退出,仅取消TCP订阅(不关闭BLoC)');
|
||||
_logger.log('🚫 [DeviceStatusBloc] 页面退出,仅取消TCP订阅(不关闭BLoC)');
|
||||
_tcpSubscription?.cancel();
|
||||
//_tcpSubscription?.cancel();
|
||||
// 🔥 关键修复:不调用 super.close(),保持 BLoC 活跃
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class DeviceStatusCubit extends Cubit<DeviceStatusState> {
|
||||
|
||||
_stringMessageSub?.cancel();
|
||||
|
||||
_stringMessageSub = _dispatcher.onStringMessage().listen((message) {
|
||||
_stringMessageSub = _dispatcher.onStringMessageOfdeviceStatus().listen((message) {
|
||||
if (message.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user