test_widget_fix.md 4.0 KB

卡片更新机制修复测试

修复内容

问题分析

  1. 重复监听器问题:每个卡片都注册了监听器,导致同一个状态更新被多次处理
  2. 部分卡片更新失败:某些卡片ID总是更新失败
  3. 监听器重复触发:同一个状态变化触发了多次监听器调用

解决方案

  1. 单一全局监听器:只在 initializeServices 时设置一次监听器
  2. 统一更新机制:使用 updateAllWidgetsWithData 统一处理所有卡片
  3. 避免重复注册:移除了每个卡片的单独监听器注册
  4. 简化初始化:卡片初始化只负责初始数据加载

代码修改

1. 添加全局监听器标志

private globalListenerSetup: boolean = false;

2. 修改initializeServices方法

private initializeServices(): void {
  if (!this.widgetDataManager) {
    this.widgetDataManager = new WidgetDataManager();
    hilog.info(0x0000, TAG, 'WidgetDataManager initialized');
  }
  
  // 设置全局状态监听器(只设置一次)
  if (!this.globalListenerSetup) {
    this.setupGlobalStateListener();
    this.globalListenerSetup = true;
  }
}

3. 新增全局监听器设置方法

private setupGlobalStateListener(): void {
  try {
    const avSessionListener = AvSessionWidgetListener.getInstance();
    avSessionListener.addStateListener((data: WidgetData) => {
      hilog.info(0x0000, TAG, `Heanup widget global listener received state update: isPlaying=${data.playState.isPlaying}, title=${data.currentSong.title}`);
      
      // 更新所有活跃的卡片
      this.updateAllWidgetsWithData(data);
    });
    
    hilog.info(0x0000, TAG, 'Heanup widget global state listener setup successfully');
  } catch (error) {
    hilog.error(0x0000, TAG, `Heanup widget failed to setup global listener: ${error}`);
  }
}

4. 新增统一更新方法

private updateAllWidgetsWithData(data: WidgetData): void {
  this.formSizeMap.forEach((size: WidgetSize, formId: string) => {
    try {
      // 根据卡片尺寸适配数据
      const adaptedData = this.layoutManager.adaptDataForSize(data, size);
      
      hilog.info(0x0000, TAG, `Heanup widget ${formId} calling formProvider.updateForm with isPlaying=${adaptedData.isPlaying}`);
      
      // 直接使用系统API更新卡片
      const formData = formBindingData.createFormBindingData(adaptedData);
      formProvider.updateForm(formId, formData).then(() => {
        hilog.info(0x0000, TAG, `Heanup widget ${formId} updated successfully: isPlaying=${adaptedData.isPlaying}, title=${adaptedData.songTitle}`);
      }).catch((error) => {
        hilog.error(0x0000, TAG, `Heanup widget ${formId} update failed: ${error}`);
      });
    } catch (error) {
      hilog.error(0x0000, TAG, `Heanup widget ${formId} process error: ${error}`);
    }
  });
}

5. 简化initializeWidget方法

  • 移除了重复的监听器注册
  • 移除了定期更新机制
  • 只保留初始化数据加载

预期效果

日志输出应该显示:

  1. ✅ 只有一个 "global state listener setup successfully" 消息
  2. ✅ 状态更新时只有一个 "global listener received state update" 消息
  3. ✅ 所有活跃卡片都会被统一更新
  4. ✅ 减少更新失败的情况

不应该再看到:

  • ❌ 重复的监听器注册消息
  • ❌ 同一个状态更新被多次处理
  • ❌ 大量的更新失败消息

测试步骤

  1. 启动应用并添加桌面卡片
  2. 播放音乐,观察日志输出
  3. 暂停/播放切换,检查所有卡片是否同步更新
  4. 添加多个卡片,验证统一更新机制
  5. 检查日志中是否还有重复监听器问题

关键改进点

  1. 架构优化:从"每卡片一个监听器"改为"全局单一监听器"
  2. 性能提升:减少了重复的监听器调用和状态处理
  3. 稳定性增强:统一的更新机制减少了更新失败的可能性
  4. 代码简化:移除了复杂的重复逻辑,提高了可维护性