RoomStore 专职负责 AtomicXCore 中的房间事务管理,提供从房间创建到解散的完整流程控制接口。通过 RoomStore 提供的接口(例如获取及更新房间信息),可高效开发出一套成熟的房间管理体系。核心功能
创建并加入房间:房主通过调用该接口可以直接创建并进入房间。
加入房间:参与者通过调用该接口可以直接进入已存在的房间。
离开房间:参与者通过调用该接口可以退出已进入的房间。
结束房间:房主通过调用该接口可以结束当前房间,如果房间内还有其他参与者,此时参与者会收到
onRoomEnded事件。更新房间信息:房主或管理员通过调用该接口可以更新房间信息,目前支持更新房间名称,房间密码。
获取房间信息:通过调用该接口可以获取房间的详细信息。
核心概念
在开始集成之前,需要通过下表了解一下
RoomStore相关的几个核心概念:核心概念 | 核心职责与描述 |
代表房间信息的核心数据模型,封装了房间的完整信息和状态管理能力。 核心功能包括: 房间基本信息管理(房间 ID、名称、创建者)。 实时状态跟踪(参与者数量、房间状态、创建时间)。 房间调度功能(预约时间、参会者列表、提醒设置)。 全面的权限控制(密码保护、设备管控、消息管理)。 | |
代表房间状态管理的核心数据结构,负责维护用户的房间相关状态信息。 核心属性: scheduledRoomList 存储了当前账号下所有预约的房间列表信息。scheduledRoomListCursor 则代表预约房间列表的分页快照。currentRoom 则代表当前所在房间的状态信息。 | |
代表房间动态的实时事件。主要事件分为两大类:预约房间事件和房间结束事件。 | |
这是与房间全生命周期相关的核心类。功能包含:获取预约房间列表快照、执行房间管理操作,并通过 addRoomListener 方法来接收实时动态事件。 |
实现步骤
步骤1:组件集成
步骤2:创建并加入房间
实现方式:
1. 配置房间初始化参数:初始化
CreateRoomOptions创建房间配置项设置房间名称,房间密码。2. 房间权限预设:设置房间内全场成员权限,例如全体静音,全体禁画等。
3. 创建并加入房间:调用
RoomStore的createAndJoinRoom接口执行核心操作。示例代码:
import 'package:atomic_x_core/atomicxcore.dart';void createAndJoinRoom() async {// 1. 配置房间初始化参数// CreateRoomOptions 用于定义房间的基础属性及初始权限控制final options = CreateRoomOptions(roomName: '我的讨论会', // 设置房间对外展示的名称password: '', // 设置房间进入密码(若无需密码则留空)// 2. 房间权限预设isAllCameraDisabled: false, // 全员开启/禁用摄像头的初始状态isAllMessageDisabled: false, // 全员开启/禁言的初始状态isAllMicrophoneDisabled: false, // 全员开启/静音的初始状态isAllScreenShareDisabled: false, // 全员禁止/允许屏幕分享的初始状态);// 3. 创建并加入房间// 该方法会自动处理房间创建(如果不存在)和加入逻辑final result = await RoomStore.shared.createAndJoinRoom(roomID: widget.roomID,options: options,);if (result.isSuccess) {debugPrint('创建并加入房间成功');} else {debugPrint('创建并加入房间失败 [错误码: ${result.errorCode}]: ${result.errorMessage}');}}
createAndJoinRoom 接口参数详细说明
参数名 | 类型 | 必填 | 说明 |
roomID | String | 是 | 字符串类型的房间号 限制长度为 64 字节。以下为支持的字符集范围(共 89 个字符): 大小写英文字母(a-z,A-Z); 数字(0-9); 空格、 ! 、 # 、 $ 、 % 、 & 、 ( 、 ) 、 + 、 - 、 : 、 ; 、 < 、 = 、 . 、 > 、 ? 、 @ 、 [ 、 ] 、 ^ 、 _ 、 { 、 } 、 | 、 ~ 、 , 。 |
options | 是 | 房间创建选项配置对象。 |
CreateRoomOptions 结构体详细说明
参数名 | 类型 | 必填 | 默认值 | 说明 |
roomName | String | 否 | "" | 房间名称。若不设置,系统可能会使用默认名称。 |
password | String | 否 | "" | 房间密码。设置后,其他用户加入房间时需输入密码。 |
isAllMicrophoneDisabled | bool | 否 | false | 是否全员禁止开启麦克风。开启后,除房主/管理员外,普通参与者默认禁止打开麦克风。 |
isAllCameraDisabled | bool | 否 | false | 是否全员禁止开启摄像头。开启后,除房主/管理员外,普通参与者默认禁止打开摄像头。 |
isAllScreenShareDisabled | bool | 否 | false | 是否全员禁止发起屏幕共享。开启后,仅房主/管理员可进行屏幕共享。 |
isAllMessageDisabled | bool | 否 | false | 是否全员禁止发送聊天消息(禁言)。开启后,普通参与者无法在房间内发送文字消息。 |
步骤3:加入房间
import 'package:atomic_x_core/atomicxcore.dart';Future<void> joinRoom() async {// 调用 RoomStore 加入房间接口// 该操作会验证房间是否存在、用户是否被禁入以及密码是否正确final result = await RoomStore.shared.joinRoom(roomID: targetRoomID, // 目标房间 IDpassword: roomPassword, // 房间密码,若房间未设置密码则传空字符串或null);if (result.isSuccess) {print("加入房间成功");} else {print("加入房间失败 [错误码: ${result.errorCode}]: ${result.errorMessage}");}}
步骤4:离开房间
import 'package:atomic_x_core/atomicxcore.dart';Future<void> leaveRoom() async {// 1. 业务逻辑说明// leaveRoom 接口用于普通成员或房主主动退出房间// 与 endRoom 不同,房主调用 leaveRoom 只会让自己离开,房间依然存在// 2. 调用 RoomStore 离开房间接口// 该操作会停止音视频流传输,并通知服务器将当前用户移出房间final result = await RoomStore.shared.leaveRoom();if (result.code == 0) {print("离开房间成功");} else {print("离开房间失败 [错误码: ${result.errorCode}]: ${result.errorMessage}");}}
步骤5:结束房间
import 'package:atomic_x_core/atomicxcore.dart';Future<void> endRoom() async {// 1. 业务逻辑说明// endRoom 接口用于永久解散当前房间// 注意:该操作通常仅限房主(Owner)执行,解散后所有成员将被强制退出// 2. 调用 RoomStore 解散房间接口// 该方法会向服务器发送解散指令,并通知所有在线参与者房间已结束final result = await RoomStore.shared.endRoom();if (result.isSuccess) {debugPrint('结束房间成功');} else {debugPrint('结束房间失败 [错误码: ${result.errorCode}]: ${result.errorMessage}');}}
步骤6:更新房间信息
当房主期望更新房间名称或者更改房间密码时,调用
RoomStore的updateRoomInfo接口即可更新房间信息。更新后房间内的参与者会收到房间状态变更通知。import 'package:atomic_x_core/atomicxcore.dart';Future<void> updateRoomInfo() async {// 1. 配置房间更新参数// UpdateRoomOptions 用于定义需要更新的房间属性final options = UpdateRoomOptions(roomName: "新的会议室名称", // 更新房间显示名称);// 2. 设置修改标志位// modifyFlagList 用于指定具体要更新哪些字段final modifyFlagList = [UpdateRoomOptionsModifyFlag.roomName, // 标记需要更新房间名称];// 3. 调用 RoomStore 更新房间信息接口// 该方法会向服务器提交更新请求,并同步给所有房间成员final result = await RoomStore.shared.updateRoomInfo(roomID: "roomID",options: options,modifyFlagList: modifyFlagList,);if (result.isSuccess) {print("更新房间信息成功");} else {print("更新房间信息失败 [错误码: ${result.errorCode}]: ${result.errorMessage}");}}
updateRoomInfo 接口参数详细说明
参数名 | 类型 | 必填 | 说明 |
roomID | String | 是 | 字符串类型的房间唯一标识符。 限制长度为 0-48 字节。 建议仅包含数字、英文字母(区分大小写)、下划线(_)和连字符(-)。避免使用空格和中文字符。 |
options | UpdateRoomOptions | 是 | 更新房间属性配置对象。 详细用法请参考:UpdateRoomOptions 结构体详细说明 |
modifyFlag | UpdateRoomOptionsModifyFlag | 是 | 更新房间属性修改标志位。目前支持更新房间名称、房间密码。 详细用法请参考:UpdateRoomOptionsModifyFlag 详细说明。 |
UpdateRoomOptions 结构体详细说明
参数名 | 类型 | 必填 | 说明 |
roomName | String | 否 | 房间名称,可以不设置,默认为空字符串。 限制长度为 0-60 字节。 支持中英文、数字、特殊字符。 |
password | String | 否 | 房间密码,空字符串 "" 通常表示该房间不设密码。 限制长度为 0-32 字节。 推荐使用 4-8 位纯数字,方便移动端输入。设置后,其他用户加入房间时需输入密码。建议不要存储明文敏感信息。 |
UpdateRoomOptionsModifyFlag 详细说明
参数名 | 类型 | 必填 | 说明 |
roomName | int | 否 | 修改房间名称时的标识位。 当修改 UpdateRoomOptions中的roomName后,需要同步向modifyFlagList中加入roomName标识位。 |
password | int | 否 | 修改房间密码时的标识位。 当修改 UpdateRoomOptions中的password后,需要同步向modifyFlagList中加入password标识位。 |
步骤7:获取房间信息
进入房间成功后调用
RoomStore的getRoomInfo接口即可获取到房间详细信息。import 'package:atomic_x_core/atomicxcore.dart';Future<void> getRoomInfo() async {// 1. 业务逻辑说明// getRoomInfo 接口用于获取指定房间的详细信息// 可以获取房间名称、创建者、参与者数量、权限设置等完整信息// 2. 调用 RoomStore 获取房间信息接口// 该操作会从服务器获取最新的房间状态和配置信息final result = await RoomStore.shared.getRoomInfo("roomID");if (result.code == 0) {print("获取房间信息成功,roomInfo: ${result.roomInfo}");} else {print("获取房间信息失败 [错误码: ${result.errorCode}]: ${result.errorMessage}");}}
步骤8:监听房间实时事件及状态变化
订阅
RoomEvent房间内的被动事件。以订阅房间结束事件为例,示例代码如下:import 'package:atomic_x_core/atomicxcore.dart';// RoomPage 代表房间主视图class RoomPage extends StatefulWidget {const RoomPage({super.key});@overrideState<RoomPage> createState() => _RoomPageState();}class _RoomPageState extends State<RoomPage> {// 房间事件监听器late final RoomListener _roomListener;@overridevoid initState() {super.initState();/// 创建监听器,设置各事件回调_roomListener = RoomListener(onRoomEnded: (roomInfo) {print("房间已结束: ${roomInfo.roomName}");},// ... 处理其他 RoomListener 事件 ...);/// 调用此方法添加监听器,订阅房间被动事件RoomStore.shared.addRoomListener(_roomListener);}@overridevoid dispose() {// 调用此方法移除监听器,避免内存泄漏RoomStore.shared.removeRoomListener(_roomListener);super.dispose();}}
订阅
RoomState房间属性状态变化。以订阅当前所在房间信息变化为例,示例代码如下:ValueListenableBuilder(valueListenable: RoomStore.shared.state.currentRoom,builder: (context, currentRoom, _) {return Container(); // 需要监听房间信息的widget},),
API 文档
Store | 功能描述 | API文档 |
RoomStore | 房间全生命周期管理:创建并加入 / 加入 / 离开 / 结束房间 / 更新、获取房间信息 / 房间预约 / 呼叫房间外成员 / 监听房间内被动事件(如房间解散,房间信息更新等)。 |
常见问题
RoomInfo 中的参与人数(participantCount)是如何更新的?时机和频率是怎样的?
participantCount 的更新并非总是实时的,其机制如下:主动进出房间:当用户主动加入或正常退出房间时,参与人数的变更通知会即时触发。您会很快在
RoomState 中的currentRoom观察到 participantCount 的变化。异常掉线:当用户因网络问题、应用崩溃等原因异常掉线时,系统需要通过心跳机制来判断其真实状态。只有当该用户连续 90 秒没有心跳后,系统才会判定其为离线,并触发人数变更通知。
更新机制与频率控制:
无论是即时触发还是延迟触发,所有的人数变更通知都是以消息的形式在房间内广播的。
房间内每秒的消息总量有上限,单房间消息频控是每秒 40 条消息。
关键点:在“弹幕风暴”消息流量极高的场景下,如果房间内的消息速率超过了 40条/秒 的阈值,为了保证核心消息(例如弹幕)的送达,人数变更的消息可能会被频控策略丢弃。
这对开发者意味着什么?
participantCount 是一个非常接近实时的高精度估算值,但在极端高并发场景下,它可能存在短暂的延迟或数据丢失。因此,我们建议您将其用于 UI 展示,而不应作为计费、统计等需要绝对精准场景的唯一依据。