首页 > 解决方案 > 与 Room 和 SharedPreferences 交互时的最佳实践

问题描述

我正在使用一个带有“收藏夹”字段的Room表格,该字段默认为,但可以通过. 需要定期擦除并由. 这样做自然会将所有“收藏”字段恢复为.entitybooleanFalseTrueuser inputdatabasenetwork callFalse

使用SharedPreferences,我可以保留第二个持久的 Favorited 列表entities,但是重新填充Room并保留收藏夹的最干净的方法是什么?

在这里使用RxKotlin是为了清楚起见,如果不是准确的话,应该是这样的

saveEntities()
 .flatMapIterable { it }
            .map{ 
                 if (sharedPrefs.contains(it.id)) 
                       it.apply{favorite} 
                 else it }
            .toList()
            .subscribe()

或者我应该serialize列出收藏夹,将其保存到SharedPreferences,然后

val favoritesList = PrefSerializer().getFavorites
saveEntities()
 .map{ it.forEach{ 
            if (favoritesList.contains(it)) 
                it.apply{favorite} 
            else it}
  }
 .subscribe()

或者将收藏信息存储在其中是否有意义RoomSharedPreferences每次调用实体时都引用感觉像是不好的做法。

标签: androidperformancesharedpreferencesandroid-room

解决方案


我建议在 Room 中使用 2 个表,因为这样您可以使用数据库视图来组合它们。Room 可以监控表格并通过 LiveData 通知 UI。您可以在技术上监控 SharedPreferences,但我相信它实际上更乏味。

例如,这是一个数据被同步定期覆盖的表。

@Entity
data class Cheese(
    @PrimaryKey
    val id: Long,
    val name: String
)

你有一个单独的表来保存“最喜欢”的状态。

@Entity
data class CheeseFavorite(
    @PrimaryKey
    val id: Long,
    val favorite: Boolean
)

然后你可以创建一个这样的数据库视图来组合 2 个表。

@DatabaseView(
    """
    SELECT c.id, c.name, f.favorite
    FROM Cheese AS c
    LEFT OUTER JOIN CheeseFavorite AS f
    ON c.id = f.id
    """
)
data class CheeseDetail(
    val id: Long,
    val name: String,
    val favorite: Boolean?
)

可以像查询表格一样查询视图。您当然可以使用 LiveData 或 Rx 数据类型作为返回类型。

@Query("SELECT * FROM CheeseDetail")
fun all(): List<CheeseDetail>

推荐阅读