DCS/ruiyiweiUX/Assets/Scripts/DCXManager.cs

250 lines
9.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.SceneManagement;
public class DCXManager : MonoBehaviour
{
private SerialCommunicationService _serialService;
// public DataService _dataService;
private UserLogService _userLogService;
// 内存监控相关
private float _lastMemoryCheckTime = 0f;
private const float MEMORY_CHECK_INTERVAL = 60f; // 每分钟检查一次内存
// 网络错误日志限流相关
private float _lastNetworkErrorLogTime = 0f;
private const float NETWORK_ERROR_LOG_INTERVAL = 60f; // 每60秒记录一次网络错误
private int _networkErrorCount = 0;
void Awake()
{
DontDestroyOnLoad(gameObject);
#if UNITY_ANDROID && !UNITY_EDITOR
// 设置服务在Awake阶段加载文件日志也要先启动才能记录启动恢复来源。
InitializeAndroidLogger();
#endif
BootstrapServices();
// 注册Unity日志回调以捕获网络错误
Application.logMessageReceived += HandleUnityLogs;
}
void Start()
{
UIManager.Instance.ShowPanel<StandByPanel>();
}
void Update()
{
// 确保串口服务在主线程中处理接收队列
_serialService?.Update();
// 定期内存检查
CheckMemoryUsage();
}
/// <summary>
/// 定期检查内存使用情况
/// </summary>
private void CheckMemoryUsage()
{
if (Time.time - _lastMemoryCheckTime >= MEMORY_CHECK_INTERVAL)
{
var memoryUsage = System.GC.GetTotalMemory(false) / (1024 * 1024f); // MB
#if UNITY_ANDROID && !UNITY_EDITOR
// 记录内存使用到文件日志
AndroidFileLogger.Instance?.LogMemoryUsage(memoryUsage,
$"队列状态: {_serialService?.GetQueueStatus() ?? ""}");
// 安卓板上内存使用过多时强制清理
if (memoryUsage > 300) // 超过300MB时强制清理
{
AndroidFileLogger.Instance?.LogError("Memory",
$"内存过高({memoryUsage:F1}MB),开始强制清理");
Debug.LogWarning($"[内存警告] 当前内存使用: {memoryUsage:F1}MB开始强制清理");
// 清理串口队列
_serialService?.ForceCleanQueues();
// 强制垃圾回收
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.GC.Collect(); // 二次回收
var memoryAfter = System.GC.GetTotalMemory(false) / (1024 * 1024f);
AndroidFileLogger.Instance?.LogInfo("Memory",
$"清理完成: {memoryUsage:F1}MB -> {memoryAfter:F1}MB, 释放: {(memoryUsage - memoryAfter):F1}MB");
Debug.Log($"[内存清理] 清理后内存: {memoryAfter:F1}MB释放: {(memoryUsage - memoryAfter):F1}MB");
}
else if (memoryUsage > 200) // 超过200MB时记录警告
{
AndroidFileLogger.Instance?.LogInfo("Memory",
$"内存使用较高: {memoryUsage:F1}MB");
Debug.LogWarning($"[内存监控] 内存使用较高: {memoryUsage:F1}MB");
// 每30秒强制执行一次内存清理
if (Time.time % 30f < 1f)
{
_serialService?.MonitorMemoryUsage();
}
}
#else
// PC上只记录内存使用情况
if (memoryUsage > 500)
{
Debug.LogWarning($"[内存监控] 当前内存使用: {memoryUsage:F1}MB");
}
#endif
_lastMemoryCheckTime = Time.time;
}
}
#if UNITY_ANDROID && !UNITY_EDITOR
/// <summary>
/// 初始化安卓文件日志系统
/// </summary>
private void InitializeAndroidLogger()
{
try
{
// AndroidFileLogger会自动创建单例并初始化
var logger = AndroidFileLogger.Instance;
if (logger != null)
{
logger.LogInfo("DCXManager", "安卓文件日志系统已初始化");
logger.LogInfo("DCXManager", $"应用启动时间: {System.DateTime.Now:yyyy-MM-dd HH:mm:ss}");
// 记录初始内存状态
var initialMemory = System.GC.GetTotalMemory(false) / (1024 * 1024f);
logger.LogMemoryUsage(initialMemory, "应用启动");
Debug.Log($"[DCXManager] 安卓文件日志系统已启动,日志路径: {logger.GetCurrentLogFilePath()}");
}
else
{
Debug.LogError("[DCXManager] 安卓文件日志系统初始化失败");
}
}
catch (System.Exception ex)
{
Debug.LogError($"[DCXManager] 初始化安卓文件日志系统异常: {ex.Message}");
}
}
#endif
private void BootstrapServices()
{
// 首先注册数据持久化服务
if (!ServiceLocator.IsRegistered<IDataPersistenceService>())
{
ServiceLocator.Register<IDataPersistenceService>(new DataPersistenceService());
}
if (!ServiceLocator.IsRegistered<IAuthenticationService>())
{
// 使用新的持久化认证服务替代内存版本
ServiceLocator.Register<IAuthenticationService>(new PersistentAuthenticationService());
}
if(!ServiceLocator.IsRegistered<UserLogService>())
{
_userLogService = new UserLogService();
ServiceLocator.Register<UserLogService>(_userLogService);
}
// 注册串口通信服务
if (!ServiceLocator.IsRegistered<ISerialCommunicationService>())
{
_serialService = new SerialCommunicationService();
ServiceLocator.Register<ISerialCommunicationService>(_serialService);
}
if (!ServiceLocator.IsRegistered<ISystemSettingsService>())
{
ServiceLocator.Register<ISystemSettingsService>(new SystemSettingsService());
}
// if (!ServiceLocator.IsRegistered<IPowerService>())
// {
// ServiceLocator.Register<IPowerService>(new PowerService());
// }
if (!ServiceLocator.IsRegistered<IDataExportService>())
{
ServiceLocator.Register<IDataExportService>(new DataExportService());
}
if (!ServiceLocator.IsRegistered<IPatientInfoService>())
{
ServiceLocator.Register<IPatientInfoService>(new PatientInfoService());
}
// if (!ServiceLocator.IsRegistered<IDataService>())
// {
// ServiceLocator.Register<IDataService>(_dataService);
// }
// 注册患者会话服务
if (!ServiceLocator.IsRegistered<PatientSessionService>())
{
ServiceLocator.Register<PatientSessionService>(new PatientSessionService());
}
}
void OnDestroy()
{
// 取消注册日志回调
Application.logMessageReceived -= HandleUnityLogs;
}
/// <summary>
/// 处理Unity日志实现网络错误限流
/// </summary>
private void HandleUnityLogs(string logString, string stackTrace, LogType type)
{
// 只处理Error和Exception类型的日志
if (type != LogType.Error && type != LogType.Exception)
return;
// 检测是否为网络相关错误
bool isNetworkError = logString.Contains("Network is unreachable") ||
logString.Contains("network") ||
logString.Contains("Network");
if (!isNetworkError)
return;
// 网络错误计数
_networkErrorCount++;
// 每60秒记录一次避免日志刷屏
if (Time.time - _lastNetworkErrorLogTime >= NETWORK_ERROR_LOG_INTERVAL)
{
Debug.Log($"[DCXManager] Unity底层网络检查(已忽略): {logString}");
_lastNetworkErrorLogTime = Time.time;
#if UNITY_ANDROID && !UNITY_EDITOR
AndroidFileLogger.Instance?.LogInfo("Network",
$"Unity网络错误(过去{NETWORK_ERROR_LOG_INTERVAL}秒): {_networkErrorCount}次");
// 记录详细信息以便调试
if (_networkErrorCount == 1)
{
AndroidFileLogger.Instance?.LogInfo("Network",
$"首次网络错误详情: {logString}");
}
#endif
// 重置计数器
_networkErrorCount = 0;
}
// 注意不触发GC不做其他重操作
// 网络错误是Unity Native层行为不影响串口通信
}
}