Android仓库模式:网络响应与Room实体类的映射实现
实现NewsRemote到NewsLocal的实体映射逻辑
先假设你有如下典型的远程数据类和Room本地实体类结构(如果你的结构不同,只需对应调整字段映射即可):
// 远程接口返回的数据类 data class NewsRemote( val id: String, val title: String, val content: String, val publishTime: Long, val author: AuthorRemote ) data class AuthorRemote( val authorId: String, val authorName: String ) // Room本地实体类 @Entity(tableName = "news") data class NewsLocal( @PrimaryKey val id: String, val title: String, val content: String, @ColumnInfo(name = "publish_time") val publishTime: Long, val authorId: String, val authorName: String )
1. 单实体映射:实现toLocal()扩展函数
在Kotlin中,你可以给NewsRemote添加一个扩展函数,直接完成字段的一一映射,包括嵌套子实体的处理:
// 建议把所有映射函数放在单独的文件(比如EntityMappers.kt)中,保持代码整洁 fun NewsRemote.toLocal(): NewsLocal { return NewsLocal( id = this.id, title = this.title, content = this.content, publishTime = this.publishTime, authorId = this.author.authorId, authorName = this.author.authorName ) }
2. 批量列表映射:处理新闻列表场景
如果接口返回的是新闻列表,给List<NewsRemote>也写个扩展函数,批量转换:
fun List<NewsRemote>.toLocalList(): List<NewsLocal> { return this.map { it.toLocal() } }
3. 特殊场景处理
字段不匹配/类型转换
如果远程字段和本地实体的字段名、类型不一致,直接在映射时做转换:
// 示例:远程返回的是字符串格式的时间,本地存时间戳 fun NewsRemote.toLocal(): NewsLocal { val publishTimestamp = try { SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) .parse(this.publishDate)?.time ?: 0L } catch (e: ParseException) { 0L } return NewsLocal( id = this.id, title = this.title, publishTime = publishTimestamp, // 其他字段映射... ) }
空值兜底
如果远程接口可能返回空字段,而Room实体字段要求非空,必须做兜底处理:
title = this.title ?: "无标题", content = this.content ?: "暂无内容"
多层嵌套实体拆分
如果远程有多层嵌套结构,可根据Room的表设计选择:
- 扁平化存储:把嵌套字段直接拆到主实体中(如上面的author字段)
- 关联表存储:给嵌套实体单独建Room表,通过外键关联主实体
Repository层使用示例
class NewsRepository( private val newsApi: NewsApi, private val newsDao: NewsDao ) { suspend fun fetchAndSaveNews() { // 从远程获取数据 val remoteNewsList = newsApi.getLatestNews() // 转换为本地实体 val localNewsList = remoteNewsList.toLocalList() // 存入Room数据库 newsDao.insertAll(localNewsList) } }
内容的提问来源于stack exchange,提问作者Techchai Mobile
相关产品推荐
相关产品推荐

