`RoomStore` 是 `AtomicXCore` 的房间管理核心模块，涵盖了预定房间体系。本章节详细介绍了如何利用 `RoomStore` 高效完成预定房间功能的开发与接入。

## 核心功能
- **预定、取消预定房间**：任何用户均可完成预定房间，取消预定房间功能。

- **更新预定房间信息：**对已预定的房间进行房间信息更新，包含：房间名称，开始时间，结束时间。

- **获取预定房间列表**：获取当前账户下所有预定的房间列表信息。

- **获取预定房间的参与成员列表**：获取指定预定房间的参与成员列表信息。

- **添加、移除预定房间参与成员**：对已预定的房间可以添加、移除参与成员。

## 核心概念

在开始集成之前，可通过下表了解 `RoomStore` 的核心概念：
| **核心概念** | **类型** | **核心职责与描述** |
| --- | --- | --- |
| [RoomStatus](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-state/index.html) | `enum class` | 代表当前房间的状态，包含：<br>- `SCHEDULED`（预定状态）。<br>- `RUNNING`（进行中）。 |
| [ScheduleRoomOptions](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-schedule-room-options/index.html) | `data class` | 代表预定房间的核心数据结构，包含：开始时间，结束时间，预定成员列表等。 |
| [RoomState](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-state/index.html) | `data class` | 代表房间状态管理的核心数据结构，负责维护用户的房间相关状态信息。<br>核心属性：<br>- `scheduledRoomList`存储了当前账号下所有预定的房间列表信息。<br>- `scheduledRoomListCursor` 则代表预定房间列表的分页游标。 |
| [RoomListener](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-listener/index.html) | `abstract class` | 代表房间动态的实时事件。其中包含预定房间相关的事件。 |
| [RoomStore](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-store/index.html) | `abstract class` | 这是与房间全生命周期相关的核心类。通过它，您可以主动发起预定房间，获取预定房间列表等功能，并通过订阅其 `RoomListener` 来接收与预定房间相关的实时动态事件。 |

## 实现步骤

### 步骤1：组件集成

请参考 接入概览 集成 **AtomicXCore SDK**，并已完成 实现登录逻辑 部分接入。

### 步骤2：预定房间功能

#### **1. 预定房间**

##### 实现方式：
  1. **配置预定房间初始化参数：**初始化`ScheduleRoomOptions`预定房间配置项设置房间命名，房间密码、开始时间、结束时间、参与者、房间信息等。

  2. **房间权限预设：**设置房间内全场成员权限，例如全体静音，全体禁画等。

  3. **预定房间：**调用`RoomStore`的`scheduleRoom`接口执行核心操作。

##### 示例代码：
``` java
import io.trtc.tuikit.atomicxcore.api.CompletionHandler
import io.trtc.tuikit.atomicxcore.api.room.RoomStore
import io.trtc.tuikit.atomicxcore.api.room.ScheduleRoomOptions

// 预定房间
fun scheduleRoom() {
    val startTime = (System.currentTimeMillis() / 1000) + 60 * 15 // 计算预定时间：当前时间 + 15分钟后开始
    val endTime = startTime + 60 * 30 // 计算结束时间：开始时间 + 30分钟（房间持续30分钟）
    val reminderSeconds = 60 * 5 // 设置提醒时间：房间开始前5分钟提醒

    // 创建预定房间选项配置
    val options = ScheduleRoomOptions(
        roomName = "房间名称",
        scheduleStartTime = startTime,
        scheduleEndTime = endTime,
        reminderSecondsBeforeStart = reminderSeconds,
        scheduleAttendees = listOf("user01", "user02", "user03"), // 设置预定参与者列表（用户ID数组）
        password = "房间密码", // 设置房间密码（可选，空字符串表示无密码）
        isAllMicrophoneDisabled = false, // 设置是否默认禁用所有参与者的麦克风（false = 允许开启麦克风）
        isAllCameraDisabled = false, // 设置是否默认禁用所有参与者的摄像头（false = 允许开启摄像头）
        isAllScreenShareDisabled = false, // 设置是否默认禁用所有参与者的屏幕共享（false = 允许屏幕共享）
        isAllMessageDisabled = false // 设置是否默认禁用所有参与者的消息功能（false = 允许发送消息）
    )

    RoomStore.shared().scheduleRoom("roomID", options, object : CompletionHandler {
        override fun onSuccess() {
            println("预定房间成功")
        }
        override fun onFailure(code: Int, desc: String) {
            println("预定房间失败: [错误码: $code] $desc")
        }
    })
}
```

##### scheduleRoom 接口参数详细说明
| 参数名 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `roomID` | `String` | 是 | - 字符串类型的房间唯一标识符。<br>- 限制长度为 0-48 字节。<br>- 建议仅包含数字、英文字母（区分大小写）、下划线（_）和连字符（-）。避免使用空格和中文字符。 |
| `options` | `ScheduleRoomOptions` | 是 | - 创建房间配置对象。<br>- 详细用法请参考：ScheduleRoomOptions 结构体详细说明。 |
| `completion` | `CompletionHandler` | 否 | 操作完成回调，用于返回预定房间的结果。若预定失败则会返回错误码和错误信息。 |

##### ScheduleRoomOptions 结构体详细说明
| 参数名 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `roomName` | `String` | 否 | - 房间名称，可以不设置，默认为空字符串。<br>- 限制长度为 0-60 字节。<br>- 支持中英文、数字、特殊字符。 |
| `password` | `String` | 否 | - 房间密码，空字符串 "" 通常表示该房间不设密码。<br>- 限制长度为 0-32 字节。<br>- 推荐使用 4-8 位纯数字，方便移动端输入。设置后，其他用户加入房间时需输入密码。建议不要存储明文敏感信息。 |
| `scheduleStartTime` | `Long` | 是 | - 预定的房间开始时间（Unix 时间戳，单位：秒）。<br>- 取值必须大于当前时间。<br>- 推荐设置为未来的整分时间。例如：1736164800（代表 2025-01-06 20:00:00）。 |
| `scheduleEndTime` | `Long` | 是 | - 预定的房间结束时间（Unix 时间戳，单位：秒）。<br>- 取值必须大于 `scheduleStartTime`。<br>- 建议根据预期时长设置。例如：`scheduleStartTime` + 3600（预定 1 小时时长的房间）。 |
| `reminderSecondsBeforeStart` | `Int` | 否 | - 房间开始前的提醒时间（单位：秒）。用于系统触发开始提醒。<br>- 推荐设置为 300（5分钟）或 900（15分钟），用于在 App 端触发本地通知。 |
| `scheduleAttendees` | `List<String>` | 否 | - 预定参与者的用户 ID 列表，在预定房间时设置，系统将向这些用户发送预定邀请。<br>- 获取方式请参考 获取指定预定房间的参与成员列表。 |
| `isAllMicrophoneDisabled` | `Boolean` | 否 | 是否全员禁止打开麦克风。开启后，除房主/管理员外，普通参与者默认禁止打开麦克风。<br>- true : 禁止。<br>- false ：取消禁止 （默认值）。 |
| `isAllCameraDisabled` | `Boolean` | 否 | 是否全员禁止打开摄像头。开启后，除房主/管理员外，普通参与者默认禁止打开摄像头。<br>- true : 禁止。<br>- false ：取消禁止（默认值）。 |
| `isAllScreenShareDisabled` | `Boolean` | 否 | 是否全员禁止发起屏幕共享。开启后，仅房主/管理员可进行屏幕共享。<br>- true : 禁止。<br>- false ：取消禁止（默认值）。 |
| `isAllMessageDisabled` | `Boolean` | 否 | 是否全员禁止发送聊天消息（禁言）。开启后，普通参与者无法在房间内发送文字消息。<br>- true : 禁止。<br>- false ：取消禁止（默认值）。 |

#### **2. 取消房间预定**

房间预定者调用 `RoomStore` 的 `cancelScheduledRoom` 接口，实现取消预定房间功能。
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.CompletionHandler
import io.trtc.tuikit.atomicxcore.api.room.RoomStore

// 取消预定房间
fun cancelScheduledRoom(roomID: String) {
    RoomStore.shared().cancelScheduledRoom(roomID, object : CompletionHandler {
        override fun onSuccess() {
            Log.d("Room", "取消预定房间成功")
        }

        override fun onFailure(code: Int, desc: String) {
            Log.d("Room", "取消预定房间失败: [错误码: $code] $desc")
        }
    })
}
```

#### **3. 更新预定房间**

房间预定者调用 `RoomStore` 的 `updateScheduledRoom` 接口，实现更新预定**房间名称**、**开始时间**、**结束时间**。
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.CompletionHandler
import io.trtc.tuikit.atomicxcore.api.room.RoomStore
import io.trtc.tuikit.atomicxcore.api.room.ScheduleRoomOptions

// 更新预定房间
fun updateScheduledRoom() {
    val newStartTime = (System.currentTimeMillis() / 1000) + 60 * 30 // 计算预定时间：当前时间 + 30分钟后开始
    val newEndTime = newStartTime + 60 * 45 // 计算结束时间：开始时间 + 45分钟（房间持续45分钟）

    val options = ScheduleRoomOptions(
        roomName = "房间名称",
        scheduleStartTime = newStartTime,
        scheduleEndTime = newEndTime
    )

    val modifyFlagList = listOf(
        ScheduleRoomOptions.ModifyFlag.ROOM_NAME,
        ScheduleRoomOptions.ModifyFlag.SCHEDULE_START_TIME,
        ScheduleRoomOptions.ModifyFlag.SCHEDULE_END_TIME
    )

    RoomStore.shared().updateScheduledRoom("roomID", options, modifyFlagList, object : CompletionHandler {
        override fun onSuccess() {
            Log.d("Room", "更新预定房间成功")
        }

        override fun onFailure(code: Int, desc: String) {
            Log.d("Room", "更新预定房间失败: [错误码: $code] $desc")
        }
    })
}
```

##### updateScheduledRoom 接口参数详细说明
| 参数名 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `roomID` | `String` | 是 | 字符串类型的房间唯一标识符。<br>限制长度为 0-48 字节。<br>建议仅包含数字、英文字母（区分大小写）、下划线（_）和连字符（-）。避免使用空格和中文字符。 |
| `options` | `ScheduleRoomOptions` | 是 | 预定房间配置对象。<br>详细用法请参考：ScheduleRoomOptions 结构体详细说明。 |
| `modifyFlag` | `ScheduleRoomOptions.ModifyFlag` | 是 | 更新房间属性修改标志位。目前支持更新**房间名称**、**开始时间**、**结束时间。**<br>详细用法请参考：ScheduleRoomOptions.ModifyFlag 详细说明。 |
| `completion` | `CompletionHandler` | 否 | 操作完成回调，用于返回更新预定房间的结果。若更新失败则会返回错误码和错误信息。 |

**ScheduleRoomOptions.ModifyFlag 详细说明**
| 参数名 | 类型 | 说明 |
| --- | --- | --- |
| `ROOM_NAME` | `enum` | - 修改预定房间名称时的标识位。<br>- 当修改 `ScheduleRoomOptions` 中的 `roomName` 后，需要同步设置 `ModifyFlag` 的 `ROOM_NAME` 标识位。 |
| `SCHEDULE_START_TIME` | `enum` | - 修改预定房间开始时间时的标识位。<br>- 当修改 `ScheduleRoomOptions` 中的 `scheduleStartTime` 后，需要同步设置 `ModifyFlag` 的 `SCHEDULE_START_TIME` 标识位。 |
| `SCHEDULE_END_TIME` | `enum` | - 修改预定房间结束时间时的标识位。<br>- 当修改 `ScheduleRoomOptions` 中的 `scheduleEndTime` 后，需要同步设置 `ModifyFlag` 的 `SCHEDULE_END_TIME` 标识位。 |

#### **4. 添加、删除参与成员**

房间预定者调用 `RoomStore` 的 `addScheduledAttendees` 或者 `removeScheduledAttendees` 接口，可以为已预定的房间内批量添加或移除预定参与者。
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.CompletionHandler
import io.trtc.tuikit.atomicxcore.api.room.RoomStore

// 添加预定参与者
fun addScheduledAttendees(roomID: String, userIDList: List<String>) {
    RoomStore.shared().addScheduledAttendees(roomID, userIDList, object : CompletionHandler {
        override fun onSuccess() {
            Log.d("Room","添加预定参与者成功")
        }
        override fun onFailure(code: Int, desc: String) {
            Log.d("Room","添加预定参与者失败: [错误码: $code] $desc")
        }
    })
}

// 移除预定参与者
fun removeScheduledAttendees(roomID: String, userIDList: List<String>) {
    RoomStore.shared().removeScheduledAttendees(roomID, userIDList, object : CompletionHandler {
        override fun onSuccess() {
            Log.d("Room","移除预定参与者成功")
        }
        override fun onFailure(code: Int, desc: String) {
            Log.d("Room","移除预定参与者失败: [错误码: $code] $desc")
        }
    })
}
```

### 步骤3：获取预定房间列表

调用 `RoomStore` 的 `getScheduledRoomList` 接口，可获取到自己账号下所有预定的房间列表信息。
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.ListResultCompletionHandler
import io.trtc.tuikit.atomicxcore.api.room.RoomInfo
import io.trtc.tuikit.atomicxcore.api.room.RoomStore

// 获取预定房间列表
fun getScheduledRoomList(cursor: String? = null) {
    // cursor 为分页游标，首次调用时传入 null，获取第一页数据， 后续调用时传入上次返回的 nextCursor 值
    RoomStore.shared().getScheduledRoomList(cursor, object : ListResultCompletionHandler<RoomInfo> {
        override fun onSuccess(result: List<RoomInfo>, cursor: String) {
            Log.d("Room", "获取预定房间列表成功")
        }

        override fun onFailure(code: Int, desc: String) {
            Log.d("Room", "获取预定房间列表失败: [错误码: $code] $desc")
        }
    })
}
```

### 步骤4：获取指定预定房间的参与成员列表

调用 `RoomStore` 的 `getScheduledAttendees` 接口，可获取到指定预定房间的参与成员列表信息。
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.ListResultCompletionHandler
import io.trtc.tuikit.atomicxcore.api.room.RoomStore
import io.trtc.tuikit.atomicxcore.api.room.RoomUser

// 获取预定房间的参与者列表
fun getScheduledAttendees(roomID: String, cursor: String? = null) {
    // cursor 为分页游标，首次调用时传入 null，获取第一页数据， 后续调用时传入上次返回的 nextCursor 值
    RoomStore.shared().getScheduledAttendees(roomID, cursor, object : ListResultCompletionHandler<RoomUser> {
        override fun onSuccess(result: List<RoomUser>, cursor: String) {
            Log.d("Room","获取预定房间参与者列表成功")
        }

        override fun onFailure(code: Int, desc: String) {
            Log.d("Room","获取预定房间参与者列表失败: [错误码: $code] $desc")
        }
    })
}
```

### 步骤5：监听预定房间实时事件及状态变化

订阅 `RoomListener` 预定房间相关的被动事件，示例代码如下：
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.room.RoomInfo
import io.trtc.tuikit.atomicxcore.api.room.RoomListener
import io.trtc.tuikit.atomicxcore.api.room.RoomStore
import io.trtc.tuikit.atomicxcore.api.room.RoomUser

/**
 * 订阅预定房间相关事件
 */
fun subscribeScheduledRoomEvents() {
    val listener = object : RoomListener() {
        override fun onAddedToScheduledRoom(roomInfo: RoomInfo) {
            Log.d("Room","已被添加到预定房间 房间信息: $roomInfo")
        }

        override fun onRemovedFromScheduledRoom(roomInfo: RoomInfo, operator: RoomUser) {
            Log.d("Room","已被移除预定房间 房间信息: $roomInfo, 移除者: $operator")
        }

        override fun onScheduledRoomCancelled(roomInfo: RoomInfo, operator: RoomUser) {
            Log.d("Room", "预定房间被取消 房间信息: $roomInfo, 取消者: $operator")
        }

        override fun onScheduledRoomStartingSoon(roomInfo: RoomInfo) {
            Log.d("Room","预定房间即将开始 房间信息: $roomInfo")
        }

        // 可以根据需要重写其他事件回调方法
    }

    RoomStore.shared().addRoomListener(listener)
}
```

订阅 `RoomState` 预定房间列表状态变化，示例代码如下：
``` java
import android.util.Log
import io.trtc.tuikit.atomicxcore.api.room.RoomStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

// 订阅预定房间列表状态变化
private fun subscribeParticipantState() {
    CoroutineScope(Dispatchers.Main).launch {
        RoomStore.shared().state.scheduledRoomList.collect { scheduledRoomList ->
            Log.d("Room", "预定房间列表变化 房间列表信息: $scheduledRoomList")
        }
    }
}
```

## API 文档
| **Store/Component** | **功能描述** | **API 文档** |
| --- | --- | --- |
| **RoomStore** | 房间全生命周期管理：创建并加入 / 加入 / 离开 / 结束房间 / 更新、获取房间信息 / 房间预定 / 呼叫房间外成员 / 监听房间内被动事件（例如房间解散，房间信息更新等）。 | [API 文档](https://tencent-rtc.github.io/TUIKit_Android/-atomic-x%20-core%20-a-p-i/io.trtc.tuikit.atomicxcore.api.room/-room-store/index.html) |

## 常见问题

### 当预定房间后，无法收到`RoomListener`的`onScheduledRoomStartingSoon`事件。

如果您在预定房间后未收到即将开始的事件通知，请按照以下两个核心要点进行检查：
1. **检查提醒参数配置** (`reminderSecondsBeforeStart`)

  - 触发机制：`onScheduledRoomStartingSoon` 事件的触发高度依赖于预定配置类 `ScheduleRoomOptions` 中的 `reminderSecondsBeforeStart` 属性。

  - 默认行为：该属性的默认值为 0，代表“不开启提醒”。

  - 解决建议：请确保在预定房间时明确设置该参数。该参数单位为**秒**，表示在房间开始前多少秒推送事件通知。

2. **验证预定时间逻辑**

  - 计算公式：系统触发提醒的前提是：预定开始时间 (`scheduleStartTime`) - 当前时间 > 提醒偏移量 (`reminderSecondsBeforeStart`)。

  - 场景说明：如果您的房间开始时间设置得过近（例如 5 分钟后开始），而提醒时间设置得过大（例如设置 10 分钟前提醒），系统将无法捕捉到触发时机，从而导致事件丢失。

  - 解决建议：请确保预定的开始时间距离当前时刻，大于您所设置的提醒秒数。
