فهرست منبع

预留2套卡片管理存储

chendeben 1 سال پیش
والد
کامیت
6b6ae4b36a

+ 160 - 291
entry/src/main/ets/common/service/UnifiedPlayerService.ets

@@ -10,7 +10,7 @@ import {
 } from './PlayerStateModel';
 import { PlaylistModel } from './PlaylistModel';
 import { IjkMediaPlayer, LogUtils, InterruptEvent, InterruptHintType } from '@ohos/ijkplayer';
-import { common } from '@kit.AbilityKit';
+import { common, Context } from '@kit.AbilityKit';
 import { PreferencesUtil as PuraPreferencesUtil, StrUtil } from '@pura/harmony-utils';
 import {
   DataPersistenceService,
@@ -39,6 +39,21 @@ import { FormRdbHelper } from '../../database/FormRdbHelper';
 import { FormInfo } from '../../viewmodel/FormInfo';
 import { WidgetDataRdbHelper } from '../../database/WidgetDataRdbHelper';
 import { WidgetDataInfo } from '../../viewmodel/WidgetDataInfo';
+import { PreferencesUtil, IWidgetData } from '../utils/PreferencesUtil';
+
+/**
+ * 存储方式枚举
+ */
+enum WidgetDataStorageType {
+  DATABASE = 'database',    // 使用数据库存储
+  PREFERENCES = 'preferences' // 使用Preferences存储
+}
+
+/**
+ * 控制WidgetData存储方式的配置
+ * 可以通过修改这个值来切换存储方式
+ */
+const WIDGET_DATA_STORAGE_TYPE: WidgetDataStorageType = WidgetDataStorageType.DATABASE;
 
 /**
  * 服务就绪状态详情接口
@@ -153,19 +168,6 @@ interface CachedWidgetData {
   finalImagePath: string | null;
 }
 
-/**
- * 多歌曲缓存管理器
- * 缓存当前歌曲及其上下首歌曲的卡片数据
- */
-interface MultiSongWidgetCache {
-  // 当前歌曲的文件路径,用于标识缓存是否有效
-  currentSongPath: string;
-  // 缓存的歌曲数据,key为文件路径
-  songDataCache: Map<string, CachedWidgetData>;
-  // 预缓存任务状态,避免重复预缓存
-  preloadingPaths: Set<string>;
-}
-
 /**
  * 统一播放器服务接口
  * 提供统一的播放控制接口,替代LocalMusic中的播放器逻辑
@@ -482,7 +484,6 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
 
   // 卡片数据缓存
   private widgetDataCache: CachedWidgetData | null = null;
-  private multiSongCache: MultiSongWidgetCache | null = null;
 
   private constructor() {
     this.playerManager = PlayerManager.getInstance();
@@ -1069,11 +1070,6 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
             await this.updateAvSessionMetadata(newSong)
           }
 
-          // 触发预缓存相邻歌曲的卡片数据
-          this.preloadAdjacentSongsWidgetData().catch((error:Error) => {
-            LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Background preload after track change failed: ${error}`);
-          });
-
           LogUtils.getInstance().LOGI('UnifiedPlayerService: Widget state updated after track change');
         } catch (error) {
           LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Failed to update widgets after track change: ${error}`);
@@ -1125,14 +1121,9 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
         this.stateModel.updateCurrentSong(newCurrentSong);
       }
 
-      // 同步更新所有桌面卡片状态
-      await this.updateAllForms();
-
       // 异步预缓存相邻歌曲的卡片数据
       setTimeout(() => {
-        this.preloadAdjacentSongsWidgetData().catch((error:Error) => {
-          LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Background preload after song selection failed: ${error}`);
-        });
+        this.updateAllForms();
       }, 0);
 
     } catch (error) {
@@ -1171,36 +1162,6 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
     return this.playlistModel.getCurrentSong();
   }
 
-  /**
-   * 获取上一首歌曲信息
-   */
-  getPreviousSong(): VideoItem | null {
-    const playlist = this.getPlaylist();
-    const currentIndex = this.getCurrentIndex();
-    
-    if (playlist.length === 0 || currentIndex < 0) {
-      return null;
-    }
-    
-    const previousIndex = (currentIndex - 1 + playlist.length) % playlist.length;
-    return playlist[previousIndex] || null;
-  }
-
-  /**
-   * 获取下一首歌曲信息
-   */
-  getNextSong(): VideoItem | null {
-    const playlist = this.getPlaylist();
-    const currentIndex = this.getCurrentIndex();
-    
-    if (playlist.length === 0 || currentIndex < 0) {
-      return null;
-    }
-    
-    const nextIndex = (currentIndex + 1) % playlist.length;
-    return playlist[nextIndex] || null;
-  }
-
   getFav(): Array<VideoItem> {
     if (this.favList.length > 0) {
       return this.favList;
@@ -3048,9 +3009,17 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
         return;
       }
 
-      const formInfoList = await FormRdbHelper.getInstance(context).queryAllForms();
+      // 根据存储配置获取Form列表
+      let formInfoList: FormInfo[] = [];
+      if (WIDGET_DATA_STORAGE_TYPE === WidgetDataStorageType.DATABASE) {
+        formInfoList = await FormRdbHelper.getInstance(context).queryAllForms();
+      } else {
+        // 从Preferences获取Form列表
+        formInfoList = await this.getFormInfoListFromPreferences(context);
+      }
+      
       if (formInfoList.length === 0) {
-        LogUtils.getInstance().LOGI('UnifiedPlayerService updateAllForms: No forms found in database');
+        LogUtils.getInstance().LOGI('UnifiedPlayerService updateAllForms: No forms found');
         return;
       }
 
@@ -3058,7 +3027,7 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
       // 直接获取包含所有数据的卡片信息,包括图片。
       // 图片加载有缓存机制,对于已加载过的歌曲,此操作很快。
       // 这可以避免双阶段更新导致的UI闪烁问题(例如背景色先变默认再变主色调)。
-      const widgetData = await this.getWidgetFormData(true); // true: 加载图片
+      const widgetData = await this.getWidgetFormData(); // true: 加载图片
       if (!widgetData) {
         LogUtils.getInstance().LOGI('UnifiedPlayerService updateAllForms: Failed to get widget data.');
         return;
@@ -3150,70 +3119,54 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
       return defaultData;
     }
 
-    // 2. 处理静态数据(优先从多歌曲缓存获取)
-    this.initMultiSongCache();
-    
-    // 首先尝试从多歌曲缓存获取
-    let cachedData = this.getCachedSongData(formData.filePath);
-    
-    if (cachedData) {
-      LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Multi-cache hit for [${formData.name}].`);
-    } else {
-      // 多歌曲缓存未命中,尝试从旧的单歌曲缓存获取
-      if (this.widgetDataCache?.filePath !== formData.filePath) {
-        this.widgetDataCache = null;
-      }
+    // 2. 处理静态数据(利用缓存)
+    // 如果歌曲已切换,则清空缓存
+    if (this.widgetDataCache?.filePath !== formData.filePath) {
+      this.widgetDataCache = null;
+    }
 
-      if (this.widgetDataCache) {
-        LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Single-cache hit for [${formData.name}].`);
-        cachedData = this.widgetDataCache;
-        // 将旧缓存数据迁移到新的多歌曲缓存
-        this.multiSongCache!.songDataCache.set(formData.filePath, cachedData);
-      } else {
-        LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Cache miss for [${formData.name}], generating static data.`);
-        // 缓存完全未命中,生成并缓存静态数据
-        let finalImagePath: string | null = null;
-        if (loadImage && formData.pixelMapPath && formData.pixelMapPath.trim() !== '') {
-          if (formData.pixelMapPath.startsWith('http')) {
-            // 网络图片,走缓存/下载逻辑
-            if (this.imageCacheDir) {
-              const cacheFileName = this.generateCacheFileName(formData.pixelMapPath);
-              const cacheFilePath = `${this.imageCacheDir}/${cacheFileName}`;
-              if (await this.isCacheValid(cacheFilePath)) {
+    if (!this.widgetDataCache) {
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Cache miss for [${formData.name}], generating static data.`);
+      // 缓存未命中,生成并缓存静态数据
+      let finalImagePath: string | null = null;
+      if (loadImage && formData.pixelMapPath && formData.pixelMapPath.trim() !== '') {
+        if (formData.pixelMapPath.startsWith('http')) {
+          // 网络图片,走缓存/下载逻辑
+          if (this.imageCacheDir) {
+            const cacheFileName = this.generateCacheFileName(formData.pixelMapPath);
+            const cacheFilePath = `${this.imageCacheDir}/${cacheFileName}`;
+            if (await this.isCacheValid(cacheFilePath)) {
+              finalImagePath = cacheFilePath;
+            } else {
+              const downloadSuccess = await this.downloadImageToCache(formData.pixelMapPath, cacheFilePath);
+              if (downloadSuccess) {
                 finalImagePath = cacheFilePath;
-              } else {
-                const downloadSuccess = await this.downloadImageToCache(formData.pixelMapPath, cacheFilePath);
-                if (downloadSuccess) {
-                  finalImagePath = cacheFilePath;
-                }
               }
             }
-          } else {
-            // 本地图片
-            finalImagePath = formData.pixelMapPath;
           }
+        } else {
+          // 本地图片
+          finalImagePath = formData.pixelMapPath;
         }
-
-        cachedData = {
-          id: formData.id || '',
-          name: formData.name || '',
-          artist: formData.artist || '',
-          album: formData.album || '',
-          pixelMapPath: formData.pixelMapPath || '',
-          duration: typeof formData.duration === 'string' ? parseInt(formData.duration || '0') : (formData.duration || 0),
-          filePath: formData.filePath || '',
-          imageColorHex: '2A2A2A', // 默认颜色,UI侧会根据图片重新提取
-          finalImagePath: finalImagePath
-        };
-
-        // 同时存储到新旧缓存
-        this.widgetDataCache = cachedData;
-        this.multiSongCache!.songDataCache.set(formData.filePath, cachedData);
       }
+
+      this.widgetDataCache = {
+        id: formData.id || '',
+        name: formData.name || '',
+        artist: formData.artist || '',
+        album: formData.album || '',
+        pixelMapPath: formData.pixelMapPath || '',
+        duration: typeof formData.duration === 'string' ? parseInt(formData.duration || '0') : (formData.duration || 0),
+        filePath: formData.filePath || '',
+        imageColorHex: '2A2A2A', // 默认颜色,UI侧会根据图片重新提取
+        finalImagePath: finalImagePath
+      };
+    } else {
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Cache hit for [${formData.name}].`);
     }
 
     // 3. 组合静态和动态数据,并处理图片文件描述符
-    // cachedData 已在上面获取
+    const cachedData = this.widgetDataCache;
 
     let imgName: string = '';
 
@@ -3226,7 +3179,7 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
         imgMap[imgName] = file.fd;
         // 注意:我们不关闭这个fd,系统会在处理完卡片数据后关闭它
       } catch (error) {
-        LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Failed to open image file [${cachedData.finalImagePath}]: ${JSON.stringify(error)}`);
+        LogUtils.getInstance().LOGI(`UnifiedPlayerService: Failed to open image file [${cachedData.finalImagePath}]: ${JSON.stringify(error)}`);
         imgMap = {};
         imgName = '';
       }
@@ -3275,177 +3228,9 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
     // 将widgetData存入数据库
     this.saveWidgetDataToDatabase(widgetData, formData);
 
-    // 4. 异步预缓存相邻歌曲的卡片数据(不阻塞当前响应)
-    setTimeout(() => {
-      this.preloadAdjacentSongsWidgetData().catch((error:Error) => {
-        LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Background preload failed: ${error}`);
-      });
-      
-      // 清理过期缓存
-      this.cleanupOldCache();
-    }, 0);
-
     return widgetData;
   }
 
-  /**
-   * 初始化多歌曲缓存
-   */
-  private initMultiSongCache(): void {
-    const currentSong = this.getCurrentSong();
-    if (!currentSong || !currentSong.filePath) {
-      return;
-    }
-
-    if (!this.multiSongCache || this.multiSongCache.currentSongPath !== currentSong.filePath) {
-      this.multiSongCache = {
-        currentSongPath: currentSong.filePath,
-        songDataCache: new Map<string, CachedWidgetData>(),
-        preloadingPaths: new Set<string>()
-      };
-    }
-  }
-
-  /**
-   * 从多歌曲缓存中获取歌曲数据
-   */
-  private getCachedSongData(filePath: string): CachedWidgetData | null {
-    if (!this.multiSongCache) {
-      return null;
-    }
-    return this.multiSongCache.songDataCache.get(filePath) || null;
-  }
-
-  /**
-   * 异步预缓存歌曲的卡片数据
-   */
-  private async preloadSongWidgetData(song: VideoItem): Promise<void> {
-    if (!song || !song.filePath) {
-      return;
-    }
-
-    this.initMultiSongCache();
-
-    // 避免重复预缓存
-    if (this.multiSongCache!.preloadingPaths.has(song.filePath) || 
-        this.multiSongCache!.songDataCache.has(song.filePath)) {
-      return;
-    }
-
-    this.multiSongCache!.preloadingPaths.add(song.filePath);
-
-    try {
-      LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Preloading widget data for [${song.name}]`);
-
-      // 处理图片路径
-      let finalImagePath: string | null = null;
-      if (song.pixelMapPath && song.pixelMapPath.trim() !== '') {
-        if (song.pixelMapPath.startsWith('http')) {
-          // 网络图片,走缓存/下载逻辑
-          if (this.imageCacheDir) {
-            const cacheFileName = this.generateCacheFileName(song.pixelMapPath);
-            const cacheFilePath = `${this.imageCacheDir}/${cacheFileName}`;
-            if (await this.isCacheValid(cacheFilePath)) {
-              finalImagePath = cacheFilePath;
-            } else {
-              const downloadSuccess = await this.downloadImageToCache(song.pixelMapPath, cacheFilePath);
-              if (downloadSuccess) {
-                finalImagePath = cacheFilePath;
-              }
-            }
-          }
-        } else {
-          // 本地图片
-          finalImagePath = song.pixelMapPath;
-        }
-      }
-
-      // 创建缓存数据
-      const cachedData: CachedWidgetData = {
-        id: song.id || '',
-        name: song.name || '',
-        artist: song.artist || '',
-        album: song.album || '',
-        pixelMapPath: song.pixelMapPath || '',
-        duration: typeof song.duration === 'string' ? parseInt(song.duration || '0') : (song.duration || 0),
-        filePath: song.filePath || '',
-        imageColorHex: '2A2A2A', // 默认颜色
-        finalImagePath: finalImagePath
-      };
-
-      // 存储到缓存
-      this.multiSongCache!.songDataCache.set(song.filePath, cachedData);
-      LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Successfully preloaded widget data for [${song.name}]`);
-
-    } catch (error) {
-      LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Failed to preload widget data for [${song.name}]: ${error}`);
-    } finally {
-      // 移除预缓存状态
-      this.multiSongCache!.preloadingPaths.delete(song.filePath);
-    }
-  }
-
-  /**
-   * 预缓存当前歌曲及其上下首歌曲的卡片数据
-   */
-  private async preloadAdjacentSongsWidgetData(): Promise<void> {
-    const currentSong = this.getCurrentSong();
-    const previousSong = this.getPreviousSong();
-    const nextSong = this.getNextSong();
-
-    // 重新初始化缓存(如果当前歌曲已变化)
-    this.initMultiSongCache();
-
-    // 并行预缓存所有相关歌曲
-    const preloadTasks: Promise<void>[] = [];
-
-    if (currentSong) {
-      preloadTasks.push(this.preloadSongWidgetData(currentSong));
-    }
-    if (previousSong && previousSong.filePath !== currentSong?.filePath) {
-      preloadTasks.push(this.preloadSongWidgetData(previousSong));
-    }
-    if (nextSong && nextSong.filePath !== currentSong?.filePath && nextSong.filePath !== previousSong?.filePath) {
-      preloadTasks.push(this.preloadSongWidgetData(nextSong));
-    }
-
-    // 等待所有预缓存任务完成
-    try {
-      await Promise.all(preloadTasks);
-      LogUtils.getInstance().LOGI('UnifiedPlayerService: Completed preloading adjacent songs widget data');
-    } catch (error) {
-      LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Error during preloading adjacent songs: ${error}`);
-    }
-  }
-
-  /**
-   * 清理过期的缓存数据,保持缓存大小合理
-   */
-  private cleanupOldCache(): void {
-    if (!this.multiSongCache) {
-      return;
-    }
-
-    const currentSong = this.getCurrentSong();
-    const previousSong = this.getPreviousSong();
-    const nextSong = this.getNextSong();
-
-    // 收集当前相关的歌曲路径
-    const relevantPaths = new Set<string>();
-    if (currentSong?.filePath) relevantPaths.add(currentSong.filePath);
-    if (previousSong?.filePath) relevantPaths.add(previousSong.filePath);
-    if (nextSong?.filePath) relevantPaths.add(nextSong.filePath);
-
-    // 移除不相关的缓存
-    const cachedPaths = Array.from(this.multiSongCache.songDataCache.keys());
-    for (const path of cachedPaths) {
-      if (!relevantPaths.has(path)) {
-        this.multiSongCache.songDataCache.delete(path);
-        LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Cleaned up cache for song: ${path}`);
-      }
-    }
-  }
-
   /**
    * 计算播放进度百分比
    */
@@ -3466,7 +3251,8 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
   }
 
   /**
-   * 将widgetData存入数据库
+   * 将widgetData存入存储中
+   * 根据配置选择数据库或Preferences存储
    */
   private async saveWidgetDataToDatabase(widgetData: widgeData, formData: VideoItem): Promise<void> {
     try {
@@ -3520,14 +3306,92 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
       widgetDataInfo.totalTimeText = widgetData.totalTimeText;
       widgetDataInfo.progressPercentage = widgetData.progressPercentage;
 
-      await WidgetDataRdbHelper.getInstance(context).insertOrUpdateWidgetData(widgetDataInfo);
-      LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService saveWidgetDataToDatabase: Widget data saved to database for song: ${formData.name}`);
+      // 根据配置选择存储方式
+      if (WIDGET_DATA_STORAGE_TYPE === WidgetDataStorageType.DATABASE) {
+        await WidgetDataRdbHelper.getInstance(context).insertOrUpdateWidgetData(widgetDataInfo);
+        LogUtils.getInstance().LOGI(`UnifiedPlayerService saveWidgetDataToDatabase: Widget data saved to database for song: ${formData.name}`);
+      } else {
+        await this.saveWidgetDataToPreferences(widgetDataInfo, context);
+        LogUtils.getInstance().LOGI(`UnifiedPlayerService saveWidgetDataToDatabase: Widget data saved to preferences for song: ${formData.name}`);
+      }
       
     } catch (error) {
-      LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService saveWidgetDataToDatabase: Failed to save widget data to database: ${error}`);
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService saveWidgetDataToDatabase: Failed to save widget data to storage: ${error}`);
     }
   }
 
+  /**
+   * 将widgetData保存到Preferences
+   */
+  private async saveWidgetDataToPreferences(widgetDataInfo: WidgetDataInfo, context: Context): Promise<void> {
+    try {
+      const preferencesUtil = PreferencesUtil.getInstance();
+      const prefs = await preferencesUtil.getPreferences(context);
+      
+      // 将WidgetDataInfo转换为IWidgetData接口格式
+      const widgetData: IWidgetData = {
+        songId: widgetDataInfo.songId,
+        name: widgetDataInfo.name,
+        artist: widgetDataInfo.artist,
+        album: widgetDataInfo.album,
+        pixelMapPath: widgetDataInfo.pixelMapPath,
+        duration: widgetDataInfo.duration,
+        filePath: widgetDataInfo.filePath,
+        imgName: widgetDataInfo.imgName,
+        imageColorHex: widgetDataInfo.imageColorHex,
+        isFavorite: widgetDataInfo.isFavorite,
+        isPlaying: widgetDataInfo.isPlaying,
+        isPaused: widgetDataInfo.isPaused,
+        isLoading: widgetDataInfo.isLoading,
+        currentPosition: widgetDataInfo.currentPosition,
+        hasNext: widgetDataInfo.hasNext,
+        hasPrevious: widgetDataInfo.hasPrevious,
+        playMode: widgetDataInfo.playMode,
+        currentIndex: widgetDataInfo.currentIndex,
+        totalCount: widgetDataInfo.totalCount,
+        currentTimeText: widgetDataInfo.currentTimeText,
+        totalTimeText: widgetDataInfo.totalTimeText,
+        progressPercentage: widgetDataInfo.progressPercentage,
+        createTime: widgetDataInfo.createTime,
+        updateTime: widgetDataInfo.updateTime
+      };
+      
+      await preferencesUtil.saveWidgetData(prefs, widgetData);
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService saveWidgetDataToPreferences: Widget data saved to preferences for song: ${widgetDataInfo.name}`);
+    } catch (error) {
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService saveWidgetDataToPreferences: Failed to save widget data to preferences: ${error}`);
+    }
+  }
+
+  /**
+   * 从Preferences获取FormInfo列表
+   */
+  private async getFormInfoListFromPreferences(context: Context): Promise<FormInfo[]> {
+    try {
+      const preferencesUtil = PreferencesUtil.getInstance();
+      const prefs = await preferencesUtil.getPreferences(context);
+      
+      const formInfoDataList = await preferencesUtil.getAllFormInfos(prefs);
+      
+      // 将IFormInfo转换为FormInfo类型
+      const formInfoList: FormInfo[] = formInfoDataList.map(data => {
+        const formInfo = new FormInfo();
+        formInfo.formId = data.formId;
+        formInfo.formName = data.formName;
+        formInfo.formDimension = data.formDimension;
+        formInfo.createTime = data.createTime;
+        formInfo.updateTime = data.updateTime;
+        return formInfo;
+      });
+      
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService getFormInfoListFromPreferences: Found ${formInfoList.length} forms in preferences`);
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService getFormInfoListFromPreferences: Using context: ${context ? 'Available' : 'NULL'}, Process: ${AppStorage.get('processName') || 'Unknown'}`);
+      return formInfoList;
+    } catch (error) {
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService getFormInfoListFromPreferences: Failed to get forms from preferences: ${error}`);
+      return [];
+    }
+  }
 
   /**
    * 状态变化时更新卡片
@@ -4014,18 +3878,23 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
         LogUtils.getInstance().LOGI('UnifiedPlayerService: No context for cleanup invalid form IDs');
         return;
       }
-      // 从数据库读取所有Form信息
+      // 根据存储配置读取所有Form信息
       let formInfoList: FormInfo[] = [];
       try {
-        formInfoList = await FormRdbHelper.getInstance(this.context).queryAllForms();
-        LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService cleanupInvalidFormIds: Found ${formInfoList.length} forms in database`);
+        if (WIDGET_DATA_STORAGE_TYPE === WidgetDataStorageType.DATABASE) {
+          formInfoList = await FormRdbHelper.getInstance(this.context).queryAllForms();
+          LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService cleanupInvalidFormIds: Found ${formInfoList.length} forms in database`);
+        } else {
+          formInfoList = await this.getFormInfoListFromPreferences(this.context);
+          LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService cleanupInvalidFormIds: Found ${formInfoList.length} forms in preferences`);
+        }
       } catch (error) {
-        LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService cleanupInvalidFormIds: Failed to query forms from database: ${error}`);
+        LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService cleanupInvalidFormIds: Failed to query forms: ${error}`);
         return;
       }
 
       if (formInfoList.length === 0) {
-        LogUtils.getInstance().LOGI('UnifiedPlayerService cleanupInvalidFormIds: No forms found in database');
+        LogUtils.getInstance().LOGI('UnifiedPlayerService cleanupInvalidFormIds: No forms found');
         return;
       }
 

+ 201 - 0
entry/src/main/ets/common/utils/PreferencesUtil.ets

@@ -5,6 +5,47 @@ import { Context } from '@kit.AbilityKit';
 // 定义支持的值类型
 type SupportedValueType = string | number | boolean | Uint8Array;
 
+/**
+ * FormInfo数据接口
+ */
+export interface IFormInfo {
+  formId: string;
+  formName: string;
+  formDimension: string;
+  createTime: string;
+  updateTime: string;
+}
+
+/**
+ * WidgetData数据接口
+ */
+export interface IWidgetData {
+  songId: string;
+  name: string;
+  artist: string;
+  album: string;
+  pixelMapPath: string;
+  duration: number;
+  filePath: string;
+  imgName: string;
+  imageColorHex: string;
+  isFavorite: boolean;
+  isPlaying: boolean;
+  isPaused: boolean;
+  isLoading: boolean;
+  currentPosition: number;
+  hasNext: boolean;
+  hasPrevious: boolean;
+  playMode: number;
+  currentIndex: number;
+  totalCount: number;
+  currentTimeText: string;
+  totalTimeText: string;
+  progressPercentage: number;
+  createTime: string;
+  updateTime: string;
+}
+
 const TAG = 'PreferencesUtil';
 const FORM_IDS_KEY = 'widget_form_ids';
 const PREFERENCES_NAME = 'ttmusic_widget_prefs';
@@ -218,4 +259,164 @@ export class PreferencesUtil {
       return defaultValue;
     }
   }
+
+  /**
+   * 保存FormInfo到Preferences
+   */
+  public async saveFormInfo(prefs: preferences.Preferences, formInfo: IFormInfo): Promise<void> {
+    try {
+      const key = `form_info_${formInfo.formId}`;
+      const formData: IFormInfo = {
+        formId: formInfo.formId,
+        formName: formInfo.formName,
+        formDimension: formInfo.formDimension,
+        createTime: formInfo.createTime || new Date().toISOString(),
+        updateTime: formInfo.updateTime || new Date().toISOString()
+      };
+      
+      await prefs.put(key, JSON.stringify(formData));
+      await prefs.flush();
+      hilog.info(0x0000, TAG, `FormInfo saved to Preferences: ${formInfo.formId}`);
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to save FormInfo to Preferences: ${error}`);
+    }
+  }
+
+  /**
+   * 从Preferences获取FormInfo
+   */
+  public async getFormInfo(prefs: preferences.Preferences, formId: string): Promise<IFormInfo | null> {
+    try {
+      const key = `form_info_${formId}`;
+      const formDataStr = await prefs.get(key, '') as string;
+      if (formDataStr) {
+        const formData = JSON.parse(formDataStr) as IFormInfo;
+        hilog.info(0x0000, TAG, `FormInfo retrieved from Preferences: ${formId}`);
+        return formData;
+      }
+      return null;
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to get FormInfo from Preferences: ${error}`);
+      return null;
+    }
+  }
+
+  /**
+   * 从Preferences移除FormInfo
+   */
+  public async removeFormInfo(prefs: preferences.Preferences, formId: string): Promise<void> {
+    try {
+      const key = `form_info_${formId}`;
+      if (await prefs.has(key)) {
+        await prefs.delete(key);
+        await prefs.flush();
+        hilog.info(0x0000, TAG, `FormInfo removed from Preferences: ${formId}`);
+      } else {
+        hilog.warn(0x0000, TAG, `FormInfo not found in Preferences for removal: ${formId}`);
+      }
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to remove FormInfo from Preferences: ${error}`);
+    }
+  }
+
+  /**
+   * 获取所有存储在Preferences中的FormInfo
+   */
+  public async getAllFormInfos(prefs: preferences.Preferences): Promise<IFormInfo[]> {
+    try {
+      const formInfos: IFormInfo[] = [];
+      const formIds = await this.getFormIds(prefs);
+      
+      for (const formId of formIds) {
+        const formInfo = await this.getFormInfo(prefs, formId);
+        if (formInfo) {
+          formInfos.push(formInfo);
+        }
+      }
+      
+      hilog.info(0x0000, TAG, `Retrieved ${formInfos.length} FormInfos from Preferences`);
+      return formInfos;
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to get all FormInfos from Preferences: ${error}`);
+      return [];
+    }
+  }
+
+  /**
+   * 保存WidgetData到Preferences
+   */
+  public async saveWidgetData(prefs: preferences.Preferences, widgetData: IWidgetData): Promise<void> {
+    try {
+      const key = 'latest_widget_data';
+      const widgetDataObj: IWidgetData = {
+        songId: widgetData.songId || '',
+        name: widgetData.name || '',
+        artist: widgetData.artist || '',
+        album: widgetData.album || '',
+        pixelMapPath: widgetData.pixelMapPath || '',
+        duration: widgetData.duration || 0,
+        filePath: widgetData.filePath || '',
+        imgName: widgetData.imgName || '',
+        imageColorHex: widgetData.imageColorHex || '2A2A2A',
+        isFavorite: widgetData.isFavorite || false,
+        isPlaying: widgetData.isPlaying || false,
+        isPaused: widgetData.isPaused !== false, // 默认为暂停状态
+        isLoading: widgetData.isLoading || false,
+        currentPosition: widgetData.currentPosition || 0,
+        hasNext: widgetData.hasNext || false,
+        hasPrevious: widgetData.hasPrevious || false,
+        playMode: widgetData.playMode || 0,
+        currentIndex: widgetData.currentIndex || 0,
+        totalCount: widgetData.totalCount || 0,
+        currentTimeText: widgetData.currentTimeText || '00:00',
+        totalTimeText: widgetData.totalTimeText || '00:00',
+        progressPercentage: widgetData.progressPercentage || 0,
+        createTime: widgetData.createTime || new Date().toISOString(),
+        updateTime: new Date().toISOString()
+      };
+      
+      await prefs.put(key, JSON.stringify(widgetDataObj));
+      await prefs.flush();
+      hilog.info(0x0000, TAG, `WidgetData saved to Preferences: ${widgetData.name}`);
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to save WidgetData to Preferences: ${error}`);
+    }
+  }
+
+  /**
+   * 从Preferences获取最新的WidgetData
+   */
+  public async getLatestWidgetData(prefs: preferences.Preferences): Promise<IWidgetData | null> {
+    try {
+      const key = 'latest_widget_data';
+      const widgetDataStr = await prefs.get(key, '') as string;
+      if (widgetDataStr) {
+        const widgetData = JSON.parse(widgetDataStr) as IWidgetData;
+        hilog.info(0x0000, TAG, `WidgetData retrieved from Preferences: ${widgetData.name}`);
+        return widgetData;
+      }
+      return null;
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to get WidgetData from Preferences: ${error}`);
+      return null;
+    }
+  }
+
+  /**
+   * 从Preferences移除WidgetData
+   */
+  public async removeWidgetData(prefs: preferences.Preferences): Promise<void> {
+    try {
+      const key = 'latest_widget_data';
+      if (await prefs.has(key)) {
+        await prefs.delete(key);
+        await prefs.flush();
+        hilog.info(0x0000, TAG, `WidgetData removed from Preferences`);
+      } else {
+        hilog.warn(0x0000, TAG, `WidgetData not found in Preferences for removal`);
+      }
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to remove WidgetData from Preferences: ${error}`);
+    }
+  }
 }

+ 14 - 43
entry/src/main/ets/entryability/EntryAbility.ets

@@ -155,6 +155,7 @@ export default class EntryAbility extends UIAbility {
     }
 
   }
+  private unifiedService: UnifiedPlayerService=UnifiedPlayerService.getInstance();
 
   async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
     AppUtil.init(this.context);
@@ -547,60 +548,28 @@ export default class EntryAbility extends UIAbility {
    */
   private async sendWidgetControlEvent(command: string, params: Record<string, Object>): Promise<void> {
     try {
-      // 获取UnifiedPlayerService实例 - 基础检查
-      const unifiedService = UnifiedPlayerService.getInstance();
-      if (!unifiedService) {
+      if (!this.isServiceFullyReady) {
         hilog.error(0x0000, 'Heanup2', '❌ UnifiedPlayerService 未初始化');
         return;
       }
-
-      // 使用预缓存的服务就绪状态 - 大幅减少检查时间
-      if (!this.isServiceFullyReady) {
-        hilog.info(0x0000, 'Heanup2', '⚠️ 缓存显示服务未就绪,执行快速验证...');
-        const quickValidation = await this.validateAndCacheServiceReadiness();
-        if (!quickValidation) {
-          hilog.warn(0x0000, 'Heanup2', '❌ 服务验证失败,无法执行widget控制操作');
-          return;
-        }
-      }
-
-      // 播放列表检查 - 简化版本
-      if (command === 'PLAY_PAUSE' || command === 'NEXT_SONG' || command === 'PREV_SONG') {
-        const playlist = unifiedService.getPlaylist();
-        if (playlist.length === 0) {
-          hilog.warn(0x0000, 'Heanup2', '⚠️ 播放列表为空,尝试快速数据恢复');
-          await this.forceDataRestoration(unifiedService);
-          
-          // 简化重新检查
-          const updatedPlaylist = unifiedService.getPlaylist();
-          if (updatedPlaylist.length === 0) {
-            hilog.warn(0x0000, 'Heanup2', '❌ 数据恢复后播放列表仍为空,跳过操作');
-            return;
-          }
-          hilog.info(0x0000, 'Heanup2', `✅ 播放列表恢复成功: ${updatedPlaylist.length} 首歌曲`);
-        }
-      }
-
-      hilog.info(0x0000, 'Heanup2', `⚡ 执行widget控制命令: ${command} (服务已就绪)`);
-
       // 直接执行命令 - 移除复杂的状态检查
       switch (command) {
         case 'PLAY_PAUSE':
           // 简化版本:基于服务状态直接切换
-          const currentState = unifiedService.getCurrentState();
+          const currentState = this.unifiedService.getCurrentState();
           if (currentState.isPlaying) {
-            await unifiedService.pause();
+            await this.unifiedService.pause();
           } else {
-            await unifiedService.startPlayOrResumePlay();
+            await this.unifiedService.startPlayOrResumePlay();
           }
           break;
 
         case 'NEXT_SONG':
-          await unifiedService.playNext();
+          await this.unifiedService.playNext();
           break;
 
         case 'PREV_SONG':
-          await unifiedService.playPrevious();
+          await this.unifiedService.playPrevious();
           break;
 
         case 'OPEN_APP':
@@ -608,7 +577,7 @@ export default class EntryAbility extends UIAbility {
           break;
 
         case "toggleFavorite":
-          await unifiedService.toggleFavorite();
+          await this.unifiedService.toggleFavorite();
           break;
 
         default:
@@ -618,7 +587,10 @@ export default class EntryAbility extends UIAbility {
 
       // 立即广播状态更新
       try {
-        unifiedService.broadcastCurrentState();
+        setTimeout( ()=>{
+          this.unifiedService.broadcastCurrentState();
+        },0)
+        // this.unifiedService.broadcastCurrentState();
         hilog.info(0x0000, 'Heanup2', `✅ Widget命令执行完成: ${command}`);
       } catch (error) {
         hilog.error(0x0000, 'Heanup2', `❌ 状态广播失败: ${error}`);
@@ -732,10 +704,9 @@ export default class EntryAbility extends UIAbility {
         hilog.info(0x0000, 'Heanup2', '✅ UnifiedPlayerService 异步初始化成功');
 
         // 对于冷启动场景,立即尝试数据恢复
-        const unifiedService = UnifiedPlayerService.getInstance();
-        if (!unifiedService.isDataRestorationCompleted()) {
+        if (!this.unifiedService.isDataRestorationCompleted()) {
           hilog.info(0x0000, 'Heanup2', '🔄 冷启动检测到数据未恢复,开始预恢复');
-          await unifiedService.forceDataRestoration();
+          await this.unifiedService.forceDataRestoration();
         }
 
         // 初始化完成后,立即执行一次完整的服务就绪状态检查并缓存结果

+ 164 - 22
entry/src/main/ets/entryformability/EntryFormAbility.ets

@@ -1,7 +1,7 @@
 import { formBindingData, FormExtensionAbility, formProvider } from '@kit.FormKit';
 import { Want } from '@kit.AbilityKit';
 import { hilog } from '@kit.PerformanceAnalysisKit';
-import { PreferencesUtil } from '../common/utils/PreferencesUtil';
+import { PreferencesUtil, IFormInfo, IWidgetData } from '../common/utils/PreferencesUtil';
 import { UnifiedPlayerService } from '../common/service/UnifiedPlayerService';
 import { FormRdbHelper } from '../database/FormRdbHelper';
 import { FormInfo } from '../viewmodel/FormInfo';
@@ -10,6 +10,20 @@ import { WidgetDataInfo } from '../viewmodel/WidgetDataInfo';
 
 const TAG = 'EntryFormAbility';
 
+/**
+ * 存储方式枚举
+ */
+enum FormStorageType {
+  DATABASE = 'database',    // 使用数据库存储
+  PREFERENCES = 'preferences' // 使用Preferences存储
+}
+
+/**
+ * 控制FormInfo存储方式的配置
+ * 可以通过修改这个值来切换存储方式
+ */
+const FORM_STORAGE_TYPE: FormStorageType = FormStorageType.DATABASE;
+
 
 /**
  * 桌面播放器卡片扩展能力
@@ -74,7 +88,7 @@ export default class EntryFormAbility extends FormExtensionAbility {
     console.info(`[EntryFormAbility] onAddForm called with formId: ${formId}`);
     console.info(`[EntryFormAbility] formName: ${formName}, dimension: ${formDimension}`);
 
-    // 创建FormInfo对象并保存到数据库
+    // 创建FormInfo对象并根据配置选择存储方式
     if (formId && formName && formDimension) {
       let formInfo = new FormInfo();
       formInfo.formId = formId;
@@ -83,17 +97,25 @@ export default class EntryFormAbility extends FormExtensionAbility {
 
       hilog.info(0x0000, TAG, `onAddForm formInfo: ${JSON.stringify(formInfo)}`);
 
-      // 保存到数据库
-      FormRdbHelper.getInstance(this.context).insertForm(formInfo).catch((error: Error) => {
-        hilog.error(0x0000, TAG, `Failed to insert form to database: ${error.message}`);
-      });
+      // 根据配置选择存储方式
+      if (FORM_STORAGE_TYPE === FormStorageType.DATABASE) {
+        // 保存到数据库
+        FormRdbHelper.getInstance(this.context).insertForm(formInfo).catch((error: Error) => {
+          hilog.error(0x0000, TAG, `Failed to insert form to database: ${error.message}`);
+        });
+      } else {
+        // 保存到Preferences
+        this.saveFormInfoToPreferences(formInfo).catch((error: Error) => {
+          hilog.error(0x0000, TAG, `Failed to save form to preferences: ${error.message}`);
+        });
+      }
     }
 
     // 异步获取真实数据并更新卡片
     // this.updateFormWithRealData(formId);
 
-    // 尝试从数据库获取已保存的widget数据
-    this.loadWidgetDataFromDatabase(formId);
+    // 尝试从存储中获取已保存的widget数据
+    this.loadWidgetDataFromStorage(formId);
 
     // 立即返回一个加载中的临时数据,以满足同步返回的要求
     const loadingData: GeneratedObjectLiteralInterface_1 = {
@@ -116,19 +138,59 @@ export default class EntryFormAbility extends FormExtensionAbility {
 
 
   /**
-   * 从数据库加载widget数据并更新卡片
+   * 将WidgetDataInfo转换为IWidgetData接口格式
+   */
+  private convertWidgetDataInfoToIWidgetData(widgetDataInfo: WidgetDataInfo): IWidgetData {
+    return {
+      songId: widgetDataInfo.songId,
+      name: widgetDataInfo.name,
+      artist: widgetDataInfo.artist,
+      album: widgetDataInfo.album,
+      pixelMapPath: widgetDataInfo.pixelMapPath,
+      duration: widgetDataInfo.duration,
+      filePath: widgetDataInfo.filePath,
+      imgName: widgetDataInfo.imgName,
+      imageColorHex: widgetDataInfo.imageColorHex,
+      isFavorite: widgetDataInfo.isFavorite,
+      isPlaying: widgetDataInfo.isPlaying,
+      isPaused: widgetDataInfo.isPaused,
+      isLoading: widgetDataInfo.isLoading,
+      currentPosition: widgetDataInfo.currentPosition,
+      hasNext: widgetDataInfo.hasNext,
+      hasPrevious: widgetDataInfo.hasPrevious,
+      playMode: widgetDataInfo.playMode,
+      currentIndex: widgetDataInfo.currentIndex,
+      totalCount: widgetDataInfo.totalCount,
+      currentTimeText: widgetDataInfo.currentTimeText,
+      totalTimeText: widgetDataInfo.totalTimeText,
+      progressPercentage: widgetDataInfo.progressPercentage,
+      createTime: widgetDataInfo.createTime,
+      updateTime: widgetDataInfo.updateTime
+    };
+  }
+
+  /**
+   * 从存储中加载widget数据并更新卡片
+   * 根据配置选择从数据库或Preferences加载
    * @param formId 卡片ID
    */
-  private loadWidgetDataFromDatabase(formId: string): void {
+  private loadWidgetDataFromStorage(formId: string): void {
     setTimeout(async () => {
       try {
-        hilog.info(0x0000, TAG, `[${formId}] Loading widget data from database.`);
+        let latestWidgetData: IWidgetData | null = null;
         
-        const widgetDataRdbHelper = WidgetDataRdbHelper.getInstance(this.context);
-        const latestWidgetData = await widgetDataRdbHelper.getLatestWidgetData();
+        if (FORM_STORAGE_TYPE === FormStorageType.DATABASE) {
+          hilog.info(0x0000, TAG, `[${formId}] Loading widget data from database.`);
+          const widgetDataRdbHelper = WidgetDataRdbHelper.getInstance(this.context);
+          const dbWidgetData = await widgetDataRdbHelper.getLatestWidgetData();
+          latestWidgetData = dbWidgetData ? this.convertWidgetDataInfoToIWidgetData(dbWidgetData) : null;
+        } else {
+          hilog.info(0x0000, TAG, `[${formId}] Loading widget data from preferences.`);
+          latestWidgetData = await this.loadWidgetDataFromPreferences();
+        }
         
         if (latestWidgetData) {
-          // 将数据库数据转换为卡片需要的格式
+          // 将存储数据转换为卡片需要的格式
           const formData: GeneratedObjectLiteralInterface_1 = {
             name: latestWidgetData.name || '未知歌曲',
             artist: latestWidgetData.artist || '未知艺术家',
@@ -148,14 +210,16 @@ export default class EntryFormAbility extends FormExtensionAbility {
           const bindingData = formBindingData.createFormBindingData(formData);
           await formProvider.updateForm(formId, bindingData);
           
-          hilog.info(0x0000, TAG, `[${formId}] Successfully updated form with database widget data: ${latestWidgetData.name}`);
+          const storageType = FORM_STORAGE_TYPE === FormStorageType.DATABASE ? 'database' : 'preferences';
+          hilog.info(0x0000, TAG, `[${formId}] Successfully updated form with ${storageType} widget data: ${latestWidgetData.name}`);
         } else {
-          hilog.info(0x0000, TAG, `[${formId}] No widget data found in database, will wait for real-time data.`);
+          const storageType = FORM_STORAGE_TYPE === FormStorageType.DATABASE ? 'database' : 'preferences';
+          hilog.info(0x0000, TAG, `[${formId}] No widget data found in ${storageType}, will wait for real-time data.`);
         }
       } catch (error) {
-        hilog.error(0x0000, TAG, `[${formId}] Failed to load widget data from database: ${error}`);
+        hilog.error(0x0000, TAG, `[${formId}] Failed to load widget data from storage: ${error}`);
       }
-    }, 50); // 比updateFormWithRealData稍早一些执行,优先显示数据库数据
+    }, 50); // 比updateFormWithRealData稍早一些执行,优先显示存储数据
   }
 
 
@@ -173,10 +237,18 @@ export default class EntryFormAbility extends FormExtensionAbility {
     hilog.info(0x0000, TAG, 'onRemoveForm');
     console.info(`[EntryFormAbility] onRemoveForm called for ${formId}`);
     
-    // 从数据库中删除Form信息
-    FormRdbHelper.getInstance(this.context).deleteForm(formId).catch((error: Error) => {
-      hilog.error(0x0000, TAG, `Failed to delete form from database: ${error.message}`);
-    });
+    // 根据配置选择删除方式
+    if (FORM_STORAGE_TYPE === FormStorageType.DATABASE) {
+      // 从数据库中删除Form信息
+      FormRdbHelper.getInstance(this.context).deleteForm(formId).catch((error: Error) => {
+        hilog.error(0x0000, TAG, `Failed to delete form from database: ${error.message}`);
+      });
+    } else {
+      // 从Preferences中删除Form信息
+      this.removeFormInfoFromPreferences(formId).catch((error: Error) => {
+        hilog.error(0x0000, TAG, `Failed to remove form from preferences: ${error.message}`);
+      });
+    }
   }
 
   /**
@@ -289,4 +361,74 @@ export default class EntryFormAbility extends FormExtensionAbility {
       console.error(`[EntryFormAbility] Error details:`, error);
     }
   }
+
+  /**
+   * 保存FormInfo到Preferences
+   */
+  private async saveFormInfoToPreferences(formInfo: FormInfo): Promise<void> {
+    try {
+      hilog.info(0x0000, TAG, `Saving FormInfo to Preferences: ${formInfo.formId}`);
+      
+      const preferencesUtil = PreferencesUtil.getInstance();
+      const prefs = await preferencesUtil.getPreferences(this.context);
+      
+      // 保存FormInfo - 转换为IFormInfo接口格式
+      const formInfoData: IFormInfo = {
+        formId: formInfo.formId,
+        formName: formInfo.formName,
+        formDimension: formInfo.formDimension,
+        createTime: formInfo.createTime,
+        updateTime: formInfo.updateTime
+      };
+      await preferencesUtil.saveFormInfo(prefs, formInfoData);
+      
+      // 同时添加到Form ID列表中
+      await preferencesUtil.addFormId(prefs, formInfo.formId);
+      
+      hilog.info(0x0000, TAG, `FormInfo saved to Preferences successfully: ${formInfo.formId}`);
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to save FormInfo to Preferences: ${error}`);
+      throw new Error(`Failed to save FormInfo to Preferences: ${error}`);
+    }
+  }
+
+  /**
+   * 从Preferences中移除FormInfo
+   */
+  private async removeFormInfoFromPreferences(formId: string): Promise<void> {
+    try {
+      hilog.info(0x0000, TAG, `Removing FormInfo from Preferences: ${formId}`);
+      
+      const preferencesUtil = PreferencesUtil.getInstance();
+      const prefs = await preferencesUtil.getPreferences(this.context);
+      
+      // 移除FormInfo
+      await preferencesUtil.removeFormInfo(prefs, formId);
+      
+      // 同时从Form ID列表中移除
+      await preferencesUtil.removeFormId(prefs, formId);
+      
+      hilog.info(0x0000, TAG, `FormInfo removed from Preferences successfully: ${formId}`);
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to remove FormInfo from Preferences: ${error}`);
+      throw new Error(`Failed to remove FormInfo from Preferences: ${error}`);
+    }
+  }
+
+  /**
+   * 从Preferences中加载WidgetData
+   */
+  private async loadWidgetDataFromPreferences(): Promise<IWidgetData | null> {
+    try {
+      const preferencesUtil = PreferencesUtil.getInstance();
+      const prefs = await preferencesUtil.getPreferences(this.context);
+      
+      const latestWidgetData = await preferencesUtil.getLatestWidgetData(prefs);
+      return latestWidgetData;
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to load WidgetData from Preferences: ${error}`);
+      return null;
+    }
+  }
+
 }