|
@@ -449,6 +449,7 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
private imageCacheDir: string = ''; // 图片缓存目录
|
|
private imageCacheDir: string = ''; // 图片缓存目录
|
|
|
private readonly CACHE_EXPIRY_DAYS: number = 7; // 缓存有效期:7天
|
|
private readonly CACHE_EXPIRY_DAYS: number = 7; // 缓存有效期:7天
|
|
|
private readonly MAX_CACHE_SIZE_MB: number = 50; // 最大缓存大小:50MB
|
|
private readonly MAX_CACHE_SIZE_MB: number = 50; // 最大缓存大小:50MB
|
|
|
|
|
+ private hasChecked: boolean=false;
|
|
|
|
|
|
|
|
private constructor() {
|
|
private constructor() {
|
|
|
this.playerManager = PlayerManager.getInstance();
|
|
this.playerManager = PlayerManager.getInstance();
|
|
@@ -975,10 +976,10 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
|
|
|
|
|
// 2. 检查服务是否已准备就绪
|
|
// 2. 检查服务是否已准备就绪
|
|
|
if (!this.isAllServicesReady()) {
|
|
if (!this.isAllServicesReady()) {
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: ${direction} - 服务未就绪,等待服务初始化完成`);
|
|
|
|
|
|
|
+ LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: ${direction} - 服务未就绪,等待服务初始化完成`);
|
|
|
const isReady = await this.waitForAllServicesReady(500, false);
|
|
const isReady = await this.waitForAllServicesReady(500, false);
|
|
|
if (!isReady) {
|
|
if (!isReady) {
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: Services not ready for ${direction}, skipping`);
|
|
|
|
|
|
|
+ LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Services not ready for ${direction}, skipping`);
|
|
|
// 统一处理方式:在服务未就绪时直接返回,避免抛出错误中断用户体验
|
|
// 统一处理方式:在服务未就绪时直接返回,避免抛出错误中断用户体验
|
|
|
this.isManualSongChange = false;
|
|
this.isManualSongChange = false;
|
|
|
return;
|
|
return;
|
|
@@ -1306,38 +1307,44 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
* 用于桌面卡片控制等场景,确保在执行播放控制前服务状态正常
|
|
* 用于桌面卡片控制等场景,确保在执行播放控制前服务状态正常
|
|
|
*/
|
|
*/
|
|
|
isAllServicesReady(): boolean {
|
|
isAllServicesReady(): boolean {
|
|
|
- try {
|
|
|
|
|
- // 检查基本初始化状态
|
|
|
|
|
- if (!this.isInitialized) {
|
|
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService: Service not initialized');
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (this.hasChecked){
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }else {
|
|
|
|
|
+ this.hasChecked = true;
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 检查基本初始化状态
|
|
|
|
|
+ if (!this.isInitialized) {
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Service not initialized');
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 检查核心组件是否就绪
|
|
|
|
|
- if (!this.playerManager || !this.stateModel || !this.playlistModel) {
|
|
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService: Core components not ready');
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 检查核心组件是否就绪
|
|
|
|
|
+ if (!this.playerManager || !this.stateModel || !this.playlistModel) {
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Core components not ready');
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 检查 PlayerManager 是否已经初始化
|
|
|
|
|
- const playerInstance = this.playerManager.getIjkPlayer();
|
|
|
|
|
- if (!playerInstance) {
|
|
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService: Player instance not ready');
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 检查 PlayerManager 是否已经初始化
|
|
|
|
|
+ const playerInstance = this.playerManager.getIjkPlayer();
|
|
|
|
|
+ if (!playerInstance) {
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Player instance not ready');
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 检查上下文是否可用
|
|
|
|
|
- if (!this.context) {
|
|
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService: Context not available');
|
|
|
|
|
|
|
+ // 检查上下文是否可用
|
|
|
|
|
+ if (!this.context) {
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Context not available');
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: All services ready');
|
|
|
|
|
+ return true;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Service readiness check failed: ${error}`);
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService: All services ready');
|
|
|
|
|
- return true;
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: Service readiness check failed: ${error}`);
|
|
|
|
|
- return false;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -2486,12 +2493,12 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
} else {
|
|
} else {
|
|
|
// 向后兼容的旧逻辑:根据播放器实际状态切换
|
|
// 向后兼容的旧逻辑:根据播放器实际状态切换
|
|
|
LogUtils.getInstance().LOGI('UnifiedPlayerService: widgetIsPlaying not provided, using fallback logic.');
|
|
LogUtils.getInstance().LOGI('UnifiedPlayerService: widgetIsPlaying not provided, using fallback logic.');
|
|
|
- const isActuallyPlaying = this.getActualPlayingState();
|
|
|
|
|
- if (isActuallyPlaying) {
|
|
|
|
|
- await this.pause();
|
|
|
|
|
- } else {
|
|
|
|
|
- await this.startPlayOrResumePlay();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const isActuallyPlaying = this.getActualPlayingState();
|
|
|
|
|
+ if (isActuallyPlaying) {
|
|
|
|
|
+ await this.pause();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ await this.startPlayOrResumePlay();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
LogUtils.getInstance().LOGI(`UnifiedPlayerService onPlayPause error: ${error}`);
|
|
LogUtils.getInstance().LOGI(`UnifiedPlayerService onPlayPause error: ${error}`);
|
|
@@ -2974,44 +2981,27 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // --- 两阶段更新策略 ---
|
|
|
|
|
- // 阶段一:立即更新UI状态(文本、图标等),不包含封面图,确保响应速度
|
|
|
|
|
- const dataWithoutImage = await this.getWidgetFormData(false); // false: 不加载图片
|
|
|
|
|
- if (!dataWithoutImage) {
|
|
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService updateAllForms: Failed to get widget data for phase 1.');
|
|
|
|
|
|
|
+ // --- 单阶段更新策略 ---
|
|
|
|
|
+ // 直接获取包含所有数据的卡片信息,包括图片。
|
|
|
|
|
+ // 图片加载有缓存机制,对于已加载过的歌曲,此操作很快。
|
|
|
|
|
+ // 这可以避免双阶段更新导致的UI闪烁问题(例如背景色先变默认再变主色调)。
|
|
|
|
|
+ const widgetData = await this.getWidgetFormData(true); // true: 加载图片
|
|
|
|
|
+ if (!widgetData) {
|
|
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService updateAllForms: Failed to get widget data.');
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const formBindingDataWithoutImage = formBindingData.createFormBindingData(dataWithoutImage);
|
|
|
|
|
|
|
+ const bindingData = formBindingData.createFormBindingData(widgetData);
|
|
|
// 并行更新所有卡片,提高效率
|
|
// 并行更新所有卡片,提高效率
|
|
|
- const updatePromisesPhase1 = formInfoList.map(formInfo =>
|
|
|
|
|
- formProvider.updateForm(formInfo.formId, formBindingDataWithoutImage)
|
|
|
|
|
|
|
+ const updatePromises = formInfoList.map(formInfo =>
|
|
|
|
|
+ formProvider.updateForm(formInfo.formId, bindingData)
|
|
|
);
|
|
);
|
|
|
- await Promise.all(updatePromisesPhase1);
|
|
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: Phase 1 (quick update) completed for ${formInfoList.length} forms.`);
|
|
|
|
|
-
|
|
|
|
|
- // 阶段二:异步加载封面图,然后再次更新卡片
|
|
|
|
|
- // 使用 setTimeout(0) 将其推到事件循环的下一个tick,避免阻塞当前流程
|
|
|
|
|
- setTimeout(async () => {
|
|
|
|
|
- const dataWithImage = await this.getWidgetFormData(true); // true: 加载图片(这步可能很慢)
|
|
|
|
|
- if (!dataWithImage || Object.keys(dataWithImage.formImages).length === 0) {
|
|
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService: No image to update in Phase 2.');
|
|
|
|
|
- return; // 没有图片或加载失败,则无需第二阶段更新
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const formBindingDataWithImage = formBindingData.createFormBindingData(dataWithImage);
|
|
|
|
|
- const updatePromisesPhase2 = formInfoList.map(formInfo =>
|
|
|
|
|
- formProvider.updateForm(formInfo.formId, formBindingDataWithImage)
|
|
|
|
|
- );
|
|
|
|
|
- await Promise.all(updatePromisesPhase2);
|
|
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: Phase 2 (image update) completed for ${formInfoList.length} forms.`);
|
|
|
|
|
- }, 0);
|
|
|
|
|
|
|
+ await Promise.all(updatePromises);
|
|
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: All forms updated for ${formInfoList.length} forms.`);
|
|
|
|
|
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
LogUtils.getInstance().LOGI(`UnifiedPlayerService updateAllForms error: ${error}`);
|
|
LogUtils.getInstance().LOGI(`UnifiedPlayerService updateAllForms error: ${error}`);
|
|
|
} finally {
|
|
} finally {
|
|
|
- // 关键:在阶段一完成后就立即释放标志,允许新的状态更新(不含图片)可以被触发
|
|
|
|
|
- // 阶段二的图片加载在后台进行,不应阻塞后续的状态更新
|
|
|
|
|
this.isUpdatingForms = false;
|
|
this.isUpdatingForms = false;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|