You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多账户电影类别偏好管理的Room数据库实现方案咨询

问题描述

现有应用流程

  • 用户在Login Fragment输入url和code,点击保存后发起获取token请求,成功后携带token请求电影类别数据,类别展示在RecyclerView中,点击类别进入对应影视列表Fragment。
  • token请求成功后,url与code存入AccountData实体类(以url+code拼接的totalAccountData作为主键),该实体数据展示在启动页Account Management Fragment的RecyclerView中。

需求

实现用户为每个账户自定义显示的电影类别,且可随时修改偏好(如AccountA仅显示10个类别中的5个,AccountB仅显示15个中的6个)。

当前思路与困境

已新增MovieCategorySelectFragment供用户选择类别,计划用Room实现,将MovieCategory设为Entity(以id为主键,添加可空的accountData字段关联AccountData主键),认为二者是一对多关系,但遇到以下问题:

  1. 是新建SelectedMovieCategory实体类存储选中类别,还是先将请求到的类别存入Room再处理选择逻辑?
  2. 两种方案下,如何传递AccountData的主键到MovieCategory建立关联?是否需在Dao中编写对应函数?

最终期望

在Account Management Fragment点击账户时,仅加载该账户之前选中的类别,且可进入MovieCategorySelectFragment修改偏好。

现有数据类代码

data class MovieCategoryResponse(
    val js: List<MovieCategory>
)

@Entity
@Parcelize
data class MovieCategory(
    @PrimaryKey(autoGenerate = false)
    val id: String,
    val number: Int,
    val title: String,
    
    val accountData: String? 
) : Parcelable


@Entity
data class AccountData(
    val url: String,
    val code: String,
    @PrimaryKey(autoGenerate = false)
    val totalAccountData: String
)
解决方案

推荐方案:新建关联实体存储选中关系

直接在MovieCategory中添加accountData字段会导致数据冗余(同一个类别会被多个账户重复存储),更合理的方式是新建关联实体记录账户与选中类别的映射关系:

1. 实体类调整

  • 简化MovieCategory实体,移除accountData字段(类别属于全局数据,不绑定单个账户):
@Entity
@Parcelize
data class MovieCategory(
    @PrimaryKey(autoGenerate = false)
    val id: String,
    val number: Int,
    val title: String
) : Parcelable
  • 新建SelectedMovieCategory关联实体,用复合主键避免重复选中:
@Entity(primaryKeys = ["accountId", "categoryId"])
data class SelectedMovieCategory(
    val accountId: String, // 对应AccountData的totalAccountData
    val categoryId: String // 对应MovieCategory的id
)
  • AccountData实体保持不变。

2. 数据存储流程

  • 首次获取类别:请求到MovieCategoryResponse后,用insertOrReplace将所有类别插入Room,避免重复存储。
  • 用户选择/修改类别:
    1. 获取当前账户的totalAccountData;
    2. 修改偏好时,先删除该账户对应的所有SelectedMovieCategory记录;
    3. 将用户选中的类别id与账户id组合成SelectedMovieCategory对象,批量插入Room。

3. Dao层核心函数

需要编写关联查询、插入、删除的Dao函数:

@Dao
interface MovieCategoryDao {
    // 插入/更新电影类别
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertCategories(categories: List<MovieCategory>)

    // 根据账户id查询选中的类别
    @Query("SELECT mc.* FROM MovieCategory mc JOIN SelectedMovieCategory smc ON mc.id = smc.categoryId WHERE smc.accountId = :accountId")
    suspend fun getSelectedCategoriesByAccount(accountId: String): List<MovieCategory>

    // 删除指定账户的所有选中类别记录
    @Query("DELETE FROM SelectedMovieCategory WHERE accountId = :accountId")
    suspend fun deleteSelectedCategoriesByAccount(accountId: String)

    // 插入选中的类别关联记录
    @Insert
    suspend fun insertSelectedCategories(selected: List<SelectedMovieCategory>)
}

4. 页面逻辑衔接

  • Account Management Fragment点击账户:调用getSelectedCategoriesByAccount查询该账户的选中类别,传入电影类别Fragment展示。
  • 进入MovieCategorySelectFragment修改偏好:
    1. 查询该账户已选中的类别id列表,用于页面标记已选状态;
    2. 查询Room中所有可用电影类别;
    3. 用户确认选择后,先删除旧的关联记录,再插入新的选中关联数据。

备选方案:复用MovieCategory添加选中标记(不推荐)

如果坚持复用现有MovieCategory结构,可添加选中状态字段,但会存在数据冗余问题:

  • 修改MovieCategory实体:
@Entity
@Parcelize
data class MovieCategory(
    @PrimaryKey(autoGenerate = false)
    val id: String,
    val number: Int,
    val title: String,
    val accountData: String, // 改为非空,绑定单个账户
    val isSelected: Boolean
) : Parcelable
  • Dao核心函数:
@Dao
interface MovieCategoryDao {
    // 插入账户专属类别数据
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertAccountCategories(categories: List<MovieCategory>)

    // 查询账户选中的类别
    @Query("SELECT * FROM MovieCategory WHERE accountData = :accountId AND isSelected = 1")
    suspend fun getSelectedCategoriesByAccount(accountId: String): List<MovieCategory>

    // 更新类别选中状态
    @Query("UPDATE MovieCategory SET isSelected = :isSelected WHERE id = :categoryId AND accountData = :accountId")
    suspend fun updateCategorySelection(accountId: String, categoryId: String, isSelected: Boolean)
}
  • 流程:首次获取类别时,为每个类别设置对应accountData和默认isSelected=false,插入Room;用户选择时调用updateCategorySelection修改状态。但同一个类别会被每个账户存储一次,数据冗余严重,不推荐。

内容的提问来源于stack exchange,提问作者Alex Mutschl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 11:50:31