从"幽灵回调"到"精准控制":一次事件监听系统的重构之旅

在我最近负责的HarmonyOS 6电商应用中,遇到了一个令人头疼的问题:用户反馈在商品详情页频繁点击收藏按钮时,应用会出现卡顿甚至闪退。通过性能监控发现,每次点击收藏按钮,系统会触发多次相同的回调函数,导致内存急剧上升,最终引发应用崩溃。

更诡异的是,这个问题在开发环境很难复现,只有在用户真实使用场景中才会出现。经过深入排查,我发现问题的根源在于事件监听机制的使用不当——多个组件同时监听了同一个事件,却没有正确管理监听器的生命周期。

今天,我将带你深入HarmonyOS 6的事件系统,揭示那些隐藏在回调函数中的性能"黑洞",并提供一套完整的优化方案,让你的应用从"幽灵回调"的困扰中彻底解放。

问题重现:事件监听器的"多重人格"

场景一:蓝牙状态监听的"回声效应"

让我们先看一个典型的蓝牙状态监听实现,这里隐藏着第一个性能陷阱:

// 蓝牙管理器 - 存在事件重复触发问题的版本
class BluetoothManager {
  private static instance: BluetoothManager;
  private isBluetoothEnabled: boolean = false;
  private stateChangeListeners: Function[] = [];
  
  static getInstance(): BluetoothManager {
    if (!BluetoothManager.instance) {
      BluetoothManager.instance = new BluetoothManager();
    }
    return BluetoothManager.instance;
  }
  
  // 初始化蓝牙
  async initialize() {
    try {
      // 获取蓝牙access实例
      const bluetoothAccess = await bluetooth.getBluetoothAccess();
      
      // 问题1:多次调用on方法注册同一个事件
      bluetoothAccess.on('stateChange', (state: bluetooth.BluetoothState) => {
        console.log(`[BluetoothManager] 蓝牙状态变化: ${state}`);
        this.isBluetoothEnabled = state === bluetooth.BluetoothState.STATE_ON;
        this.notifyStateChange();
      });
      
      // 问题2:在另一个地方又注册了一次
      this.setupBluetoothMonitoring();
      
      // 获取当前状态
      const state = await bluetoothAccess.getState();
      this.isBluetoothEnabled = state === bluetooth.BluetoothState.STATE_ON;
      
    } catch (error) {
      console.error(`[BluetoothManager] 初始化失败:`, error);
    }
  }
  
  // 设置蓝牙监控
  private setupBluetoothMonitoring() {
    bluetooth.getBluetoothAccess().then(access => {
      // 问题3:这里又注册了一次,但没有保存引用
      access.on('stateChange', (state: bluetooth.BluetoothState) => {
        console.log(`[BluetoothManager] 监控到蓝牙状态变化: ${state}`);
        this.handleBluetoothStateChange(state);
      });
    });
  }
  
  // 处理蓝牙状态变化
  private handleBluetoothStateChange(state: bluetooth.BluetoothState) {
    this.isBluetoothEnabled = state === bluetooth.BluetoothState.SATE_ON;
    
    // 问题4:这里又触发了一次通知
    this.notifyStateChange();
  }
  
  // 注册状态变化监听器
  addStateChangeListener(listener: Function) {
    this.stateChangeListeners.push(listener);
    console.log(`[BluetoothManager] 添加监听器,当前数量: ${this.stateChangeListeners.length}`);
  }
  
  // 移除状态变化监听器
  removeStateChangeListener(listener: Function) {
    const index = this.stateChangeListeners.indexOf(listener);
    if (index > -1) {
      this.stateChangeListeners.splice(index, 1);
      console.log(`[BluetoothManager] 移除监听器,剩余数量: ${this.stateChangeListeners.length}`);
    }
  }
  
  // 通知所有监听器
  private notifyStateChange() {
    console.log(`[BluetoothManager] 通知 ${this.stateChangeListeners.length} 个监听器`);
    
    // 问题5:这里会触发多次相同的回调
    this.stateChangeListeners.forEach(listener => {
      try {
        listener(this.isBluetoothEnabled);
      } catch (error) {
        console.error(`[BluetoothManager] 监听器执行失败:`, error);
      }
    });
  }
  
  // 清理资源
  cleanup() {
    // 问题:没有正确移除蓝牙事件监听
    // bluetoothAccess.off('stateChange', ???);
    
    this.stateChangeListeners = [];
    console.log(`[BluetoothManager] 清理完成`);
  }
}

问题表现:运行这段代码,在DevEco Studio的性能分析工具中观察,你会发现:

  1. 每次蓝牙状态变化,控制台会输出3-4条相同的日志

  2. 应用内存使用量随着状态变化次数线性增长

  3. 反复开关蓝牙后,应用响应速度明显下降

  4. 在低端设备上,频繁的状态变化会导致应用无响应

问题根源分析:事件监听的三宗罪

第一宗罪:匿名函数的身份迷失

// 错误示例:使用匿名函数导致无法正确移除
class ProblematicComponent {
  aboutToAppear() {
    // 每次aboutToAppear都会创建新的匿名函数
    bluetoothAccess.on('stateChange', (state) => {
      console.log(`状态变化: ${state}`);
      this.updateUI(state);
    });
  }
  
  aboutToDisappear() {
    // 这里无法移除监听器,因为匿名函数每次都是新的
    // bluetoothAccess.off('stateChange', ???); // 不知道要移除哪个函数
  }
}

第二宗罪:多重注册的连锁反应

// 错误示例:在多个地方注册同一个事件
class MultiRegisterComponent {
  private bluetoothAccess: any;
  
  setupListeners() {
    // 第一次注册
    this.bluetoothAccess.on('stateChange', this.handleStateChange.bind(this));
    
    // 第二次注册(可能在其他方法中)
    this.setupAdditionalListeners();
    
    // 第三次注册(可能在父组件中)
    this.parentComponent?.setupBluetoothListeners();
  }
  
  setupAdditionalListeners() {
    // 又注册了一次
    this.bluetoothAccess.on('stateChange', (state) => {
      console.log(`额外监听: ${state}`);
    });
  }
  
  // 每次状态变化,handleStateChange会被调用2-3次
  handleStateChange(state: any) {
    console.log(`处理状态变化: ${state}`);
  }
}

第三宗罪:生命周期管理缺失

// 错误示例:没有正确的生命周期管理
class LifecycleProblemComponent {
  private listeners: Map<string, Function[]> = new Map();
  
  addListener(event: string, callback: Function) {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, []);
    }
    this.listeners.get(event)?.push(callback);
    
    // 注册到系统事件
    systemEvent.on(event, callback);
  }
  
  // 问题:没有提供removeListener方法
  // 问题:没有在组件销毁时清理监听器
}

HarmonyOS 6的救赎:新一代事件监控系统

hiAppEvent:终结"盲盒式"调试

HarmonyOS 6引入了hiAppEvent框架,为事件监控带来了革命性的改进。让我们看看如何利用它来监控事件监听问题:

// 使用hiAppEvent监控事件系统
import hiAppEvent from '@ohos.hiAppEvent';

class EventMonitor {
  private static instance: EventMonitor;
  private eventWatcher: hiAppEvent.Watcher | null = null;
  private eventStats: Map<string, EventStatistics> = new Map();
  
  static getInstance(): EventMonitor {
    if (!EventMonitor.instance) {
      EventMonitor.instance = new EventMonitor();
    }
    return EventMonitor.instance;
  }
  
  // 初始化事件监控
  async initialize() {
    try {
      // 创建Watcher配置
      const config: hiAppEvent.WatcherConfig = {
        name: 'event-system-monitor',
        // 配置事件聚合策略
        params: {
          aggregation: {
            mode: 'time', // 按时间聚合
            interval: 1000, // 1秒聚合一次
            threshold: 10 // 最多10个事件批量上报
          }
        }
      };
      
      // 创建Watcher
      this.eventWatcher = await hiAppEvent.createWatcher(config);
      
      // 设置事件处理回调
      this.eventWatcher.on('receive', (events: hiAppEvent.AppEvent[]) => {
        this.processEvents(events);
      });
      
      // 启动监控
      await this.eventWatcher.start();
      
      console.log(`[EventMonitor] 事件监控系统已启动`);
      
    } catch (error) {
      console.error(`[EventMonitor] 初始化失败:`, error);
    }
  }
  
  // 监控事件注册
  trackEventRegistration(eventName: string, component: string) {
    const key = `${eventName}_${component}`;
    const stats = this.eventStats.get(key) || {
      eventName,
      component,
      registrationCount: 0,
      triggerCount: 0,
      lastRegistrationTime: 0,
      lastTriggerTime: 0
    };
    
    stats.registrationCount++;
    stats.lastRegistrationTime = Date.now();
    
    this.eventStats.set(key, stats);
    
    // 检测重复注册
    if (stats.registrationCount > 1) {
      this.reportDuplicateRegistration(eventName, component, stats.registrationCount);
    }
    
    // 上报到hiAppEvent
    hiAppEvent.write({
      domain: 'EVENT_SYSTEM',
      name: 'event_registered',
      eventType: hiAppEvent.EventType.BEHAVIOR,
      params: {
        event_name: eventName,
        component: component,
        registration_count: stats.registrationCount,
        timestamp: Date.now()
      }
    });
  }
  
  // 监控事件触发
  trackEventTrigger(eventName: string, component: string) {
    const key = `${eventName}_${component}`;
    const stats = this.eventStats.get(key);
    
    if (stats) {
      stats.triggerCount++;
      stats.lastTriggerTime = Date.now();
      
      // 检测异常触发频率
      const now = Date.now();
      const timeDiff = now - stats.lastTriggerTime;
      
      if (timeDiff < 100 && stats.triggerCount > 5) { // 100ms内触发超过5次
        this.reportHighFrequencyTrigger(eventName, component, stats.triggerCount);
      }
    }
    
    // 上报到hiAppEvent
    hiAppEvent.write({
      domain: 'EVENT_SYSTEM',
      name: 'event_triggered',
      eventType: hiAppEvent.EventType.BEHAVIOR,
      params: {
        event_name: eventName,
        component: component,
        trigger_count: stats?.triggerCount || 0,
        timestamp: Date.now()
      }
    });
  }
  
  // 报告重复注册
  private reportDuplicateRegistration(eventName: string, component: string, count: number) {
    console.warn(`[EventMonitor] 检测到重复注册: ${eventName} 在 ${component} 中被注册了 ${count} 次`);
    
    hiAppEvent.write({
      domain: 'EVENT_SYSTEM',
      name: 'duplicate_registration',
      eventType: hiAppEvent.EventType.FAULT,
      params: {
        event_name: eventName,
        component: component,
        registration_count: count,
        severity: count > 3 ? 'HIGH' : 'MEDIUM',
        timestamp: Date.now()
      }
    });
  }
  
  // 报告高频触发
  private reportHighFrequencyTrigger(eventName: string, component: string, count: number) {
    console.error(`[EventMonitor] 检测到高频触发: ${eventName} 在 ${component} 中短时间内触发了 ${count} 次`);
    
    hiAppEvent.write({
      domain: 'EVENT_SYSTEM',
      name: 'high_frequency_trigger',
      eventType: hiAppEvent.EventType.FAULT,
      params: {
        event_name: eventName,
        component: component,
        trigger_count: count,
        severity: 'CRITICAL',
        timestamp: Date.now()
      }
    });
  }
  
  // 处理监控到的事件
  private processEvents(events: hiAppEvent.AppEvent[]) {
    events.forEach(event => {
      switch (event.name) {
        case 'duplicate_registration':
          this.handleDuplicateRegistration(event);
          break;
        case 'high_frequency_trigger':
          this.handleHighFrequencyTrigger(event);
          break;
      }
    });
  }
  
  // 处理重复注册事件
  private handleDuplicateRegistration(event: hiAppEvent.AppEvent) {
    const params = event.params as any;
    console.log(`[EventMonitor] 处理重复注册: ${params.event_name} 在 ${params.component}`);
    
    // 这里可以触发自动修复或通知开发人员
    this.suggestFix(params.event_name, params.component);
  }
  
  // 处理高频触发事件
  private handleHighFrequencyTrigger(event: hiAppEvent.AppEvent) {
    const params = event.params as any;
    console.log(`[EventMonitor] 处理高频触发: ${params.event_name} 在 ${params.component}`);
    
    // 这里可以触发节流或防抖机制
    this.applyThrottle(params.event_name, params.component);
  }
  
  // 建议修复方案
  private suggestFix(eventName: string, component: string) {
    const suggestions = [
      `检查 ${component} 中 ${eventName} 事件的注册位置`,
      `确保在 aboutToDisappear 中正确移除监听器`,
      `使用具名函数而非匿名函数作为回调`,
      `考虑使用 EventHub 替代直接的事件监听`
    ];
    
    console.log(`[EventMonitor] 修复建议:`);
    suggestions.forEach(suggestion => {
      console.log(`  - ${suggestion}`);
    });
  }
  
  // 应用节流机制
  private applyThrottle(eventName: string, component: string) {
    console.log(`[EventMonitor] 对 ${eventName} 应用节流机制`);
    
    // 这里可以实现自动节流逻辑
  }
  
  // 生成监控报告
  generateReport(): EventMonitorReport {
    const report: EventMonitorReport = {
      timestamp: Date.now(),
      totalEvents: this.eventStats.size,
      duplicateRegistrations: 0,
      highFrequencyTriggers: 0,
      eventDetails: []
    };
    
    this.eventStats.forEach((stats, key) => {
      if (stats.registrationCount > 1) {
        report.duplicateRegistrations++;
      }
      
      if (stats.triggerCount > 100) { // 触发超过100次
        report.highFrequencyTriggers++;
      }
      
      report.eventDetails.push({
        eventName: stats.eventName,
        component: stats.component,
        registrationCount: stats.registrationCount,
        triggerCount: stats.triggerCount,
        lastRegistrationTime: stats.lastRegistrationTime,
        lastTriggerTime: stats.lastTriggerTime
      });
    });
    
    return report;
  }
  
  // 清理资源
  async cleanup() {
    if (this.eventWatcher) {
      await this.eventWatcher.stop();
      this.eventWatcher = null;
    }
    
    this.eventStats.clear();
    console.log(`[EventMonitor] 监控系统已清理`);
  }
}

// 事件统计类型
interface EventStatistics {
  eventName: string;
  component: string;
  registrationCount: number;
  triggerCount: number;
  lastRegistrationTime: number;
  lastTriggerTime: number;
}

// 监控报告类型
interface EventMonitorReport {
  timestamp: number;
  totalEvents: number;
  duplicateRegistrations: number;
  highFrequencyTriggers: number;
  eventDetails: EventDetail[];
}

interface EventDetail {
  eventName: string;
  component: string;
  registrationCount: number;
  triggerCount: number;
  lastRegistrationTime: number;
  lastTriggerTime: number;
}

EventHub:跨线程通信的新纪元

HarmonyOS 6对EventHub进行了重大升级,支持跨线程通信。让我们看看如何利用这一特性优化事件系统:

// 使用EventHub优化事件通信
import { EventHub } from '@ohos.base';

class OptimizedEventSystem {
  private eventHub: EventHub;
  private componentEventMap: Map<string, Set<string>> = new Map();
  
  constructor() {
    // 启用跨线程通信(仅在需要时开启)
    this.eventHub = new EventHub();
    this.eventHub.setMultithreadingEnabled(true);
  }
  
  // 安全的事件注册
  registerEvent(componentId: string, eventName: string, callback: Function): string {
    const listenerId = `${componentId}_${eventName}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    
    // 使用WeakRef避免内存泄漏
    const weakCallback = new WeakRef(callback);
    
    // 包装回调函数,添加监控
    const wrappedCallback = (...args: any[]) => {
      const callbackRef = weakCallback.deref();
      if (callbackRef) {
        // 监控事件触发
        EventMonitor.getInstance().trackEventTrigger(eventName, componentId);
        
        try {
          callbackRef(...args);
        } catch (error) {
          console.error(`[OptimizedEventSystem] 事件回调执行失败: ${eventName}`, error);
          
          // 上报错误
          hiAppEvent.write({
            domain: 'EVENT_SYSTEM',
            name: 'callback_error',
            eventType: hiAppEvent.EventType.FAULT,
            params: {
              event_name: eventName,
              component: componentId,
              error: error.message,
              timestamp: Date.now()
            }
          });
        }
      } else {
        // 回调函数已被垃圾回收,自动移除监听器
        this.unregisterEvent(eventName, listenerId);
        console.log(`[OptimizedEventSystem] 自动移除无效监听器: ${listenerId}`);
      }
    };
    
    // 注册事件
    this.eventHub.on(eventName, wrappedCallback);
    
    // 记录组件事件关系
    if (!this.componentEventMap.has(componentId)) {
      this.componentEventMap.set(componentId, new Set());
    }
    this.componentEventMap.get(componentId)?.add(listenerId);
    
    // 监控事件注册
    EventMonitor.getInstance().trackEventRegistration(eventName, componentId);
    
    console.log(`[OptimizedEventSystem] 注册事件: ${eventName}, 监听器ID: ${listenerId}`);
    
    return listenerId;
  }
  
  // 安全的事件移除
  unregisterEvent(eventName: string, listenerId: string): boolean {
    // 这里需要实现具体的移除逻辑
    // 由于EventHub的off方法需要具体的回调函数,我们需要维护一个映射表
    console.log(`[OptimizedEventSystem] 移除事件监听器: ${listenerId}`);
    return true;
  }
  
  // 清理组件所有事件
  cleanupComponentEvents(componentId: string) {
    const eventIds = this.componentEventMap.get(componentId);
    if (eventIds) {
      eventIds.forEach(listenerId => {
        // 解析事件名和监听器ID
        const parts = listenerId.split('_');
        if (parts.length >= 2) {
          const eventName = parts[1];
          this.unregisterEvent(eventName, listenerId);
        }
      });
      
      this.componentEventMap.delete(componentId);
      console.log(`[OptimizedEventSystem] 清理组件事件: ${componentId}, 移除了 ${eventIds.size} 个监听器`);
    }
  }
  
  // 触发事件(支持跨线程)
  emitEvent(eventName: string, data?: any) {
    // 在主线程触发
    this.eventHub.emit(eventName, data);
    
    // 如果需要在子线程触发
    // TaskPool.execute(() => {
    //   this.eventHub.emit(eventName, data);
    // });
  }
  
  // 获取事件统计
  getEventStatistics(): Map<string, number> {
    const stats = new Map<string, number>();
    
    this.componentEventMap.forEach((eventIds, componentId) => {
      stats.set(componentId, eventIds.size);
    });
    
    return stats;
  }
}

实战优化:重构蓝牙状态监听系统

现在让我们用新的架构重构最初的蓝牙管理器:

// 优化后的蓝牙管理器
class OptimizedBluetoothManager {
  private static instance: OptimizedBluetoothManager;
  private bluetoothAccess: any = null;
  private isBluetoothEnabled: boolean = false;
  
  // 使用WeakMap存储监听器,避免内存泄漏
  private stateChangeListeners: WeakMap<object, {
    listenerId: string;
    callback: Function;
  }> = new WeakMap();
  
  // 事件系统实例
  private eventSystem: OptimizedEventSystem;
  
  private constructor() {
    this.eventSystem = new OptimizedEventSystem();
  }
  
  static getInstance(): OptimizedBluetoothManager {
    if (!OptimizedBluetoothManager.instance) {
      OptimizedBluetoothManager.instance = new OptimizedBluetoothManager();
    }
    return OptimizedBluetoothManager.instance;
  }
  
  // 初始化蓝牙
  async initialize() {
    try {
      // 获取蓝牙access实例(只获取一次)
      if (!this.bluetoothAccess) {
        this.bluetoothAccess = await bluetooth.getBluetoothAccess();
      }
      
      // 只注册一次状态变化监听
      await this.setupStateChangeListener();
      
      // 获取当前状态
      const state = await this.bluetoothAccess.getState();
      this.isBluetoothEnabled = state === bluetooth.BluetoothState.STATE_ON;
      
      console.log(`[OptimizedBluetoothManager] 初始化完成,蓝牙状态: ${this.isBluetoothEnabled}`);
      
    } catch (error) {
      console.error(`[OptimizedBluetoothManager] 初始化失败:`, error);
      
      // 上报错误
      hiAppEvent.write({
        domain: 'BLUETOOTH',
        name: 'initialization_failed',
        eventType: hiAppEvent.EventType.FAULT,
        params: {
          error: error.message,
          timestamp: Date.now()
        }
      });
    }
  }
  
  // 设置状态变化监听(确保只注册一次)
  private async setupStateChangeListener(): Promise<void> {
    if (!this.bluetoothAccess) {
      throw new Error('蓝牙access未初始化');
    }
    
    // 检查是否已经注册
    const existingListener = this.stateChangeListeners.get(this);
    if (existingListener) {
      console.log(`[OptimizedBluetoothManager] 状态监听器已注册,跳过重复注册`);
      return;
    }
    
    // 定义状态变化处理函数(使用具名函数)
    const handleStateChange = (state: bluetooth.BluetoothState) => {
      const wasEnabled = this.isBluetoothEnabled;
      this.isBluetoothEnabled = state === bluetooth.BluetoothState.STATE_ON;
      
      console.log(`[OptimizedBluetoothManager] 蓝牙状态变化: ${state}, 之前: ${wasEnabled}, 现在: ${this.isBluetoothEnabled}`);
      
      // 使用EventHub通知状态变化,避免直接调用回调
      this.eventSystem.emitEvent('bluetoothStateChanged', {
        state: state,
        isEnabled: this.isBluetoothEnabled,
        timestamp: Date.now()
      });
      
      // 上报状态变化事件
      hiAppEvent.write({
        domain: 'BLUETOOTH',
        name: 'state_changed',
        eventType: hiAppEvent.EventType.BEHAVIOR,
        params: {
          previous_state: wasEnabled ? 'ON' : 'OFF',
          current_state: this.isBluetoothEnabled ? 'ON' : 'OFF',
          timestamp: Date.now()
        }
      });
    };
    
    // 注册监听器
    this.bluetoothAccess.on('stateChange', handleStateChange);
    
    // 保存监听器引用
    this.stateChangeListeners.set(this, {
      listenerId: 'bluetooth_state_change',
      callback: handleStateChange
    });
    
    console.log(`[OptimizedBluetoothManager] 状态变化监听器已注册`);
  }
  
  // 注册状态变化监听器(组件使用)
  registerStateChangeListener(component: object, callback: Function): string {
    const componentId = component.constructor.name;
    
    // 使用优化后的事件系统注册
    const listenerId = this.eventSystem.registerEvent(
      componentId,
      'bluetoothStateChanged',
      callback
    );
    
    console.log(`[OptimizedBluetoothManager] 组件 ${componentId} 注册了蓝牙状态监听器`);
    
    return listenerId;
  }
  
  // 移除状态变化监听器
  unregisterStateChangeListener(component: object, listenerId: string): boolean {
    const componentId = component.constructor.name;
    
    // 使用优化后的事件系统移除
    const success = this.eventSystem.unregisterEvent('bluetoothStateChanged', listenerId);
    
    if (success) {
      console.log(`[OptimizedBluetoothManager] 组件 ${componentId} 移除了蓝牙状态监听器`);
    }
    
    return success;
  }
  
  // 清理组件所有监听器
  cleanupComponentListeners(component: object) {
    const componentId = component.constructor.name;
    this.eventSystem.cleanupComponentEvents(componentId);
    console.log(`[OptimizedBluetoothManager] 清理组件 ${componentId} 的所有监听器`);
  }
  
  // 获取当前状态
  getState(): boolean {
    return this.isBluetoothEnabled;
  }
  
  // 清理资源
  async cleanup() {
    console.log(`[OptimizedBluetoothManager] 开始清理资源`);
    
    // 移除蓝牙状态监听
    const listenerInfo = this.stateChangeListeners.get(this);
    if (listenerInfo && this.bluetoothAccess) {
      try {
        this.bluetoothAccess.off('stateChange', listenerInfo.callback);
        console.log(`[OptimizedBluetoothManager] 已移除蓝牙状态监听器`);
      } catch (error) {
        console.error(`[OptimizedBluetoothManager] 移除蓝牙监听器失败:`, error);
      }
    }
    
    // 清理WeakMap
    this.stateChangeListeners = new WeakMap();
    
    // 清理事件系统
    // this.eventSystem.cleanup();
    
    this.bluetoothAccess = null;
    
    console.log(`[OptimizedBluetoothManager] 资源清理完成`);
  }
  
  // 获取事件统计
  getEventStatistics() {
    return this.eventSystem.getEventStatistics();
  }
}

组件集成:安全的事件监听实践

现在让我们看看如何在组件中安全地使用优化后的事件系统:

@Entry
@Component
struct BluetoothStatusComponent {
  @State bluetoothEnabled: boolean = false;
  @State isLoading: boolean = true;
  
  // 监听器ID,用于后续移除
  private listenerId: string = '';
  
  // 蓝牙管理器实例
  private bluetoothManager = OptimizedBluetoothManager.getInstance();
  
  aboutToAppear() {
    console.log(`[BluetoothStatusComponent] aboutToAppear`);
    
    // 初始化蓝牙
    this.initializeBluetooth();
    
    // 注册状态变化监听器(使用具名函数)
    this.listenerId = this.bluetoothManager.registerStateChangeListener(
      this,
      this.handleBluetoothStateChange.bind(this)
    );
    
    // 启动事件监控
    EventMonitor.getInstance().initialize().then(() => {
      console.log(`[BluetoothStatusComponent] 事件监控已启动`);
    });
  }
  
  aboutToDisappear() {
    console.log(`[BluetoothStatusComponent] aboutToDisappear`);
    
    // 移除状态变化监听器
    if (this.listenerId) {
      this.bluetoothManager.unregisterStateChangeListener(this, this.listenerId);
    }
    
    // 清理组件所有监听器
    this.bluetoothManager.cleanupComponentListeners(this);
    
    // 停止事件监控
    EventMonitor.getInstance().cleanup();
  }
  
  // 初始化蓝牙
  async initializeBluetooth() {
    this.isLoading = true;
    
    try {
      await this.bluetoothManager.initialize();
      this.bluetoothEnabled = this.bluetoothManager.getState();
    } catch (error) {
      console.error(`[BluetoothStatusComponent] 蓝牙初始化失败:`, error);
    } finally {
      this.isLoading = false;
    }
  }
  
  // 处理蓝牙状态变化(具名函数,便于移除)
  handleBluetoothStateChange(data: any) {
    console.log(`[BluetoothStatusComponent] 收到蓝牙状态变化:`, data);
    
    this.bluetoothEnabled = data.isEnabled;
    
    // 更新UI
    this.updateUI();
  }
  
  // 更新UI
  updateUI() {
    // 这里可以添加UI更新逻辑
    console.log(`[BluetoothStatusComponent] UI更新,蓝牙状态: ${this.bluetoothEnabled}`);
  }
  
  // 切换蓝牙状态
  async toggleBluetooth() {
    if (this.isLoading) return;
    
    this.isLoading = true;
    
    try {
      const bluetoothAccess = await bluetooth.getBluetoothAccess();
      
      if (this.bluetoothEnabled) {
        await bluetoothAccess.disableBluetooth();
      } else {
        await bluetoothAccess.enableBluetooth();
      }
      
      // 状态变化会通过事件监听器自动更新
      
    } catch (error) {
      console.error(`[BluetoothStatusComponent] 切换蓝牙状态失败:`, error);
      
      // 显示错误提示
      prompt.showToast({
        message: `操作失败: ${error.message}`,
        duration: 3000
      });
    } finally {
      this.isLoading = false;
    }
  }
  
  // 生成事件报告
  generateEventReport() {
    const monitorReport = EventMonitor.getInstance().generateReport();
    const bluetoothStats = this.bluetoothManager.getEventStatistics();
    
    console.log(`=== 事件系统监控报告 ===`);
    console.log(`生成时间: ${new Date(monitorReport.timestamp).toLocaleString()}`);
    console.log(`总事件数: ${monitorReport.totalEvents}`);
    console.log(`重复注册事件: ${monitorReport.duplicateRegistrations}`);
    console.log(`高频触发事件: ${monitorReport.highFrequencyTriggers}`);
    
    console.log(`\n=== 蓝牙事件统计 ===`);
    bluetoothStats.forEach((count, component) => {
      console.log(`组件 ${component}: ${count} 个监听器`);
    });
    
    console.log(`\n=== 事件详情 ===`);
    monitorReport.eventDetails.forEach(detail => {
      console.log(`事件: ${detail.eventName}`);
      console.log(`  组件: ${detail.component}`);
      console.log(`  注册次数: ${detail.registrationCount}`);
      console.log(`  触发次数: ${detail.triggerCount}`);
      console.log(`  最后注册: ${new Date(detail.lastRegistrationTime).toLocaleTimeString()}`);
      console.log(`  最后触发: ${new Date(detail.lastTriggerTime).toLocaleTimeString()}`);
      console.log(`---`);
    });
    
    // 保存报告到文件
    this.saveReportToFile(monitorReport);
  }
  
  // 保存报告到文件
  async saveReportToFile(report: EventMonitorReport) {
    try {
      const fileUri = 'internal://app/event_report.json';
      const reportStr = JSON.stringify(report, null, 2);
      
      // 这里可以实现文件保存逻辑
      console.log(`[BluetoothStatusComponent] 事件报告已保存`);
      
    } catch (error) {
      console.error(`[BluetoothStatusComponent] 保存报告失败:`, error);
    }
  }
  
  build() {
    Column({ space: 20 }) {
      // 标题
      Text('蓝牙状态监控')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .fontColor('#333333')
      
      // 状态显示
      Row({ space: 12 }) {
        Circle({ width: 20, height: 20 })
          .fill(this.bluetoothEnabled ? '#00FF00' : '#FF0000')
        
        Text(this.bluetoothEnabled ? '蓝牙已开启' : '蓝牙已关闭')
          .fontSize(18)
          .fontColor(this.bluetoothEnabled ? '#00AA00' : '#AA0000')
      }
      .justifyContent(FlexAlign.Center)
      
      // 切换按钮
      Button(this.bluetoothEnabled ? '关闭蓝牙' : '开启蓝牙')
        .width(200)
        .height(48)
        .backgroundColor(this.bluetoothEnabled ? '#FF4444' : '#44FF44')
        .fontColor('#FFFFFF')
        .fontSize(16)
        .fontWeight(FontWeight.Medium)
        .onClick(() => {
          this.toggleBluetooth();
        })
        .enabled(!this.isLoading)
      
      // 生成报告按钮
      Button('生成事件报告')
        .width(200)
        .height(48)
        .backgroundColor('#007DFF')
        .fontColor('#FFFFFF')
        .fontSize(16)
        .fontWeight(FontWeight.Medium)
        .onClick(() => {
          this.generateEventReport();
        })
      
      // 加载状态
      if (this.isLoading) {
        Row({ space: 8 }) {
          LoadingProgress()
            .width(20)
            .height(20)
            .color('#007DFF')
          
          Text('处理中...')
            .fontSize(14)
            .fontColor('#666666')
        }
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .padding(24)
    .backgroundColor('#F5F5F5')
  }
}

最佳实践总结

通过这次重构,我们解决了HarmonyOS 6事件监听系统中的核心问题。以下是关键的最佳实践:

1. 事件注册管理

  • 使用具名函数:避免使用匿名函数作为回调,确保能够正确移除

  • 单一注册点:确保每个事件只在一个地方注册,避免重复注册

  • WeakRef包装:使用WeakRef包装回调函数,避免内存泄漏

2. 生命周期管理

  • 对称操作:在aboutToAppear中注册的事件,必须在aboutToDisappear中移除

  • 组件级清理:提供组件级别的清理方法,确保所有监听器都被正确移除

  • WeakMap存储:使用WeakMap存储监听器引用,避免阻止垃圾回收

3. 监控与调试

  • hiAppEvent集成:利用HarmonyOS 6的hiAppEvent框架监控事件系统

  • 重复注册检测:实现自动检测重复注册事件的机制

  • 高频触发预警:监控事件触发频率,及时发现性能问题

4. 跨线程通信

  • EventHub优化:利用HarmonyOS 6增强的EventHub支持跨线程通信

  • 线程安全:确保在多线程环境下的数据安全性

  • 性能平衡:在需要时开启跨线程通信,避免不必要的性能开销

5. 错误处理

  • 异常捕获:在所有回调函数中添加try-catch块

  • 错误上报:将错误信息上报到监控系统

  • 优雅降级:在事件系统出现问题时提供降级方案

结语

HarmonyOS 6的事件系统在性能和功能上都得到了显著提升,但强大的功能也带来了更大的责任。通过本文介绍的优化方案,你可以:

  1. 彻底解决事件重复触发问题,提升应用稳定性

  2. 避免内存泄漏,确保应用长期运行的可靠性

  3. 实现精准的事件监控,快速定位性能瓶颈

  4. 利用新特性提升开发效率和用户体验

记住,好的事件系统就像城市的交通系统——需要精心的规划、严格的管理和实时的监控。只有这样才能确保信息的顺畅流通,避免"交通拥堵"和"事故频发"。

现在,拿起这些工具和最佳实践,去构建更加稳定、高效的HarmonyOS应用吧!你的用户会感谢你的精心设计,你的应用也会在激烈的市场竞争中脱颖而出。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐