7.1 KiB
7.1 KiB
BannerScheduler 使用说明
概述
BannerScheduler
是一个统一的 Banner 播放调度器,用于管理 V2 Banner 的播放队列和状态。它解决了原有代码中 Banner 队列管理分散、状态控制复杂的问题。
主要特性
1. 统一队列管理
- 集中管理所有 V2 Banner 的播放队列
- 自动处理队列的优先级排序
- 支持队列的暂停、恢复、清空等操作
2. 智能优先级排序
- 当前用户相关的 Banner 优先播放
- 当前房间相关的 Banner 次优先播放
- 其他 Banner 按队列顺序播放
3. 状态管理
- 统一的播放状态控制
- 防止多个 Banner 同时播放
- 支持暂停和恢复功能
4. 代理模式
- 通过代理模式解耦队列管理和播放逻辑
- 支持播放开始、完成等事件回调
- 便于进行单元测试和功能扩展
使用方法
1. 初始化
// 在 RoomAnimationView 中初始化
- (void)setupBanner {
_roomBannertModelsQueueV2 = [NSMutableArray array];
// 初始化 Banner 调度器
self.bannerScheduler = [[BannerScheduler alloc] initWithDelegate:self];
}
2. 实现代理协议
@interface RoomAnimationView () <BannerSchedulerDelegate>
// ... 其他协议
@end
@implementation RoomAnimationView
#pragma mark - BannerSchedulerDelegate
- (void)bannerScheduler:(BannerScheduler *)scheduler shouldPlayBanner:(id)banner {
// 将 Banner 数据转换为 AttachmentModel 并播放
if ([banner isKindOfClass:[AttachmentModel class]]) {
AttachmentModel *attachment = (AttachmentModel *)banner;
[self _playBannerWithAttachment:attachment];
}
}
- (void)bannerSchedulerDidFinishPlaying:(BannerScheduler *)scheduler {
// Banner 播放完成,可以在这里进行清理工作
NSLog(@"🔄 BannerScheduler: Banner 播放完成");
}
- (void)bannerScheduler:(BannerScheduler *)scheduler didStartPlayingBanner:(id)banner {
// Banner 开始播放
NSLog(@"🔄 BannerScheduler: Banner 开始播放 - 类型: %@", [banner class]);
}
@end
3. 添加 Banner 到队列
// 替换原有的队列添加逻辑
- (void)inserBannerModelToQueue:(AttachmentModel *)obj {
// 参数验证
if (!obj || ![obj isKindOfClass:[AttachmentModel class]]) {
NSLog(@"⚠️ 警告: inserBannerModelToQueue 接收到无效参数: %@", obj);
return;
}
// 使用新的调度器
[self.bannerScheduler enqueueBanner:obj];
}
4. 在 Banner 播放完成后通知调度器
- (void)playBroveBanner:(AttachmentModel *)obj {
if (!obj.data) {
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished]; // 通知调度器播放完成
return;
}
self.isRoomBannerV2Displaying = YES;
@kWeakify(self);
RoomInfoModel *roomInfo = self.hostDelegate.getRoomInfo;
[BravoGiftBannerView display:self.bannerContainer
inRoomUid:roomInfo.uid
with:obj
complete:^{
@kStrongify(self);
NSLog(@"🔄 BravoGiftBannerView complete 回调被调用");
self.isRoomBannerV2Displaying = NO;
[self.bannerScheduler markBannerFinished]; // 通知调度器播放完成
} exitCurrentRoom:^{
@kStrongify(self);
[self.hostDelegate exitRoom];
}];
}
API 参考
主要方法
队列管理
enqueueBanner:
- 添加 Banner 到播放队列processNextBanner
- 处理队列中的下一个 BannerclearQueue
- 清空播放队列sortQueueByPriority
- 根据优先级对队列进行排序
状态控制
pause
- 暂停播放(保持队列状态)resume
- 恢复播放markBannerFinished
- 标记 Banner 播放完成
信息查询
isQueueEmpty
- 检查队列是否为空bannerAtIndex:
- 获取队列中指定索引的 BannerremoveBannerAtIndex:
- 移除队列中指定索引的 BannerqueueStatusDescription
- 获取队列状态信息(用于调试)
属性
bannerQueue
- Banner 播放队列(只读)isPlaying
- 当前是否正在播放 Banner(只读)delegate
- 调度器代理queueCount
- 队列中的 Banner 数量(只读)
迁移指南
从原有代码迁移
-
替换队列添加逻辑
// 原有代码 [self.roomBannertModelsQueueV2 addObject:obj]; // 新代码 [self.bannerScheduler enqueueBanner:obj];
-
替换播放完成回调
// 原有代码 [self processNextRoomEffectAttachment]; // 新代码 [self.bannerScheduler markBannerFinished];
-
移除原有的队列管理代码
- 删除
roomBannertModelsQueueV2
属性 - 删除
isRoomBannerV2Displaying
属性 - 删除
processNextRoomEffectAttachment
方法 - 删除
sortBannerQueue
方法
- 删除
注意事项
- 类型安全:BannerScheduler 使用
id
类型,在代理方法中需要进行类型检查 - 状态同步:原有的
isRoomBannerV2Displaying
状态仍然保留,用于向后兼容 - 错误处理:在 Banner 播放失败时,也要调用
markBannerFinished
通知调度器
性能优化
1. 队列长度控制
- 建议设置最大队列长度,避免内存占用过多
- 可以在
enqueueBanner:
方法中添加队列长度检查
2. 优先级计算优化
- 当前的优先级计算在每次排序时都会执行
- 可以考虑缓存优先级计算结果,减少重复计算
3. 内存管理
- 确保在适当的时机调用
clearQueue
清空队列 - 在 RoomAnimationView 销毁时清理调度器
扩展功能
1. 添加新的 Banner 类型
在 _playBannerWithAttachment:
方法中添加新的 case 分支:
case Custom_Message_Sub_New_Banner_Type:
[self playNewBannerType:attachment];
break;
2. 自定义优先级算法
修改 sortQueueByPriority
方法,添加自定义的优先级计算逻辑。
3. 添加队列监控
通过代理方法实现队列状态的实时监控和统计。
故障排除
常见问题
-
Banner 不播放
- 检查是否正确调用了
markBannerFinished
- 检查代理方法是否正确实现
- 查看控制台日志确认调度器状态
- 检查是否正确调用了
-
队列排序不正确
- 检查 Banner 数据的
uidList
和roomUid
字段 - 确认
AccountInfoStorage.instance.getUid
返回正确的用户ID
- 检查 Banner 数据的
-
内存泄漏
- 确保在适当的时机调用
clearQueue
- 检查是否有循环引用
- 确保在适当的时机调用
调试技巧
-
使用队列状态描述
NSLog(@"队列状态: %@", [self.bannerScheduler queueStatusDescription]);
-
启用详细日志 在 BannerScheduler 中已经添加了详细的日志输出,可以通过控制台查看调度器的运行状态。
-
单元测试 创建模拟的 Banner 数据和代理对象,测试调度器的各种功能。
总结
BannerScheduler 通过统一的队列管理和状态控制,简化了 Banner 播放的复杂度,提高了代码的可维护性和可扩展性。通过合理的代理模式设计,保持了与现有代码的兼容性,同时为未来的功能扩展提供了良好的基础。