手把手教你玩转Room:Android数据库的保命指南

移动开发 Android
听说你要搞Android本地数据库?别慌!Room这货就是官方给的救命稻草,不用再被原生SQLite虐到脱发了。今天咱们用简单的方式,掰开揉碎了讲讲这玩意儿怎么玩,保你半小时上手!

听说你要搞Android本地数据库?别慌!Room这货就是官方给的救命稻草,不用再被原生SQLite虐到脱发了。今天咱们用简单的方式,掰开揉碎了讲讲这玩意儿怎么玩,保你半小时上手!

三大金刚(核心组件)

数据身份证(Entity)

这玩意儿就是数据库里的表格模板,用注解就能搞事情。举个栗子:

@Entity(tableName = "肥宅快乐表")  // 表名随便起
dataclass 宅男(
    @PrimaryKey(autoGenerate = true)
    val 编号: Int = 0,  // 自动生成主键
    
    @ColumnInfo(name = "江湖称号")// 给字段起花名
    val 昵称: String,
    
    val 年龄: Int,
    
    @ColumnInfo(defaultValue = "false")
    val 是否单身: Boolean
)

//👇

@Entity(tableName = "Otaku")
dataclass Otaku(
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0,
    @ColumnInfo(name = "name")
    val name: String, 
    val age: Int,
    @ColumnInfo(defaultValue = "false")
    val isSingle: Boolean
)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.

小贴士:@Index可以给常用字段加速,但别乱加,跟吃蛋白粉一样适量才好

专属服务员(DAO)

定义怎么调戏数据库,增删改查都能整:

@Dao
interface 宅男管家 {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspendfun 新增宅男(宅男: 宅男)

    @Query("SELECT * FROM 肥宅快乐表 WHERE 是否单身 = 1")
    fun 查所有单身狗(): Flow<List<宅男>>
}

//👇

@Dao
interface OtakuDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspendfun insert(otaku: Otaku)

    @Query("SELECT * FROM Otaku WHERE isSingle = 1")
    fun getSingleOtakus(): Flow<List<Otaku>> 
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

数据城堡(Database)

管着整个数据库的家当:

@Database(entities = [宅男::class], version = 1)
abstract class 宅男宇宙 : RoomDatabase() {
    abstract fun 管家(): 宅男管家
}

//👇

@Database(entities = [Otaku::class], version = 1)
abstract class OtakuDatabase : RoomDatabase() {
    abstract fun otakuDao(): OtakuDao // 保持管家服务
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

实例教学

第一步:加装备胎

在module的build.gradle里塞这些:

dependencies {
    // 基础三件套
    implementation "androidx.room:room-runtime:2.6.1"
    kapt "androidx.room:room-compiler:2.6.1"
    implementation "androidx.room:room-ktx:2.6.1"
    
    // 可选外挂
    implementation "androidx.room:room-paging:2.6.1" // 分页加载
    implementation "androidx.room:room-rxjava3:2.6.1" // 给RxJava爱好者
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

第二步:搞点事情

在ViewModel里调戏数据库:

class 宅男管理局(privateval 管家: 宅男管家) : ViewModel() {
    // 实时监控所有单身狗
    val 单身贵族: Flow<List<宅男>> = 管家.查所有单身狗()
        .flowOn(Dispatchers.IO)  // 后台线程保流畅
    
    fun 新增成员(昵称: String, 年龄: Int) {
        viewModelScope.launch {
            管家.新增宅男(宅男(昵称 = 昵称, 年龄 = 年龄))
            // 自动生成ID美滋滋
        }
    }
}

//👇

class OtakuViewModel(privateval otakuDao: OtakuDao) : ViewModel() {
    val singleOtakus: Flow<List<Otaku>> = otakuDao.getSingleOtakus()
        .flowOn(Dispatchers.IO)

    fun addOtaku(name: String, age: Int) {
        viewModelScope.launch {
            otakuDao.insert(
                Otaku(name = name, age = age, isSingle = true)
            )
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

坑爹预警(必看保命)

主线程禁忌

别在主线程搞数据库!Room会直接给你甩脸崩溃。用协程、RxJava或者LiveData保平安。调试时可以开allowMainThreadQueries(),但上线前一定记得删!

版本升级翻车现场

改表结构时记得升级version,建议用Migration类处理。实在懒可以用:

fallbackToDestructiveMigration()
  • 1.

但会删数据!(别问我怎么知道的)

索引的玄学

高频查询字段加索引,但每个索引会让写入速度下降。主键自带索引,不用重复加。

类型转换骚操作

想存Date类型?用TypeConverter变身:

class TimestampConverter {
    @TypeConverter
    fun dateToTimestamp(date: Date?) = date?.time 
    
    @TypeConverter
    fun timestampToDate(timestamp: Long?) = timestamp?.let { Date(it) }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

版本进化史

版本

系统

黑科技

2.2.x

4.1+

协程支持、预装数据库

2.5.x

4.1+

自动迁移、Upsert操作

2.6.x

4.1+

性能起飞、全文搜索

高阶玩法(装逼必备)

联合作战(Room+Hilt)

@Module
@InstallIn(RoomComponent::class)
object 数据库装备库 {
    @Provides
    @Singleton
    fun 召唤数据库(上下文: Context): 宅男宇宙 {
        return 宅男宇宙.启动基地(上下文)
    }
    
    @Provides
    fun 召唤管家(数据库: 宅男宇宙): 宅男管家 {
        return 数据库.管家()
    }
}

// 在ViewModel里直接召唤
@HiltViewModel
class 高级管理局 @Inject constructor(
    privateval 管家: 宅男管家
) : ViewModel() {  }

//👇

@Module
@InstallIn(RoomComponent::class)
object DatabaseModule {
    @Provides
    @Singleton
    fun provideDatabase(context: Context): OtakuDatabase {
        return OtakuDatabase.getDatabase(context)
    }

    @Provides
    fun provideDao(database: OtakuDatabase): OtakuDao {
        return database.otakuDao()
    }
}

@HiltViewModel
class OtakuViewModel @Inject constructor(privateval otakuDao: OtakuDao) : ViewModel() {
   
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.

骚操作合集

  • @Transaction保证多个操作原子性
  • @RawQuery直接写原生SQL(慎用!)
  • @Relation处理一对多关系
  • @Fts4搞全文搜索(2.6+专属)

总结

Room这玩意儿就像乐高积木

  • 🧱 Entity是基础积木块
  • 🔧 DAO是组装说明书
  • 🏗️ Database就是乐高城堡

记住:官方给的轮子使劲用就完事了,别总想着自己造轮子!遇到问题多查官方文档,保你头发茂密~

最后送大家一张Room护身符:

SELECT * FROM 头发 WHERE 状态 = '茂密';
  • 1.

责任编辑:武晓燕 来源: 沐雨花飞碟
相关推荐

2020-11-27 07:38:43

MongoDB

2011-06-28 12:58:44

表分区

2019-10-22 14:30:11

机器学习人工智能计算机

2021-07-14 09:00:00

JavaFX开发应用

2021-09-30 18:27:38

数据仓库ETL

2011-01-10 14:41:26

2011-05-03 15:59:00

黑盒打印机

2022-07-14 07:34:26

windowsmysqlcentos

2017-09-05 13:01:11

CocoaPods开源库GitHub

2021-09-26 16:08:23

CC++clang_forma

2015-07-28 14:27:44

2023-04-26 12:46:43

DockerSpringKubernetes

2022-07-27 08:16:22

搜索引擎Lucene

2022-03-14 14:47:21

HarmonyOS操作系统鸿蒙

2022-01-08 20:04:20

拦截系统调用

2022-12-07 08:42:35

2011-04-21 10:32:44

MySQL双机同步

2022-02-15 09:03:07

Pythonmofish库代码

2017-05-18 12:45:35

数据分析数据理解数据

2011-02-22 13:46:27

微软SQL.NET
点赞
收藏

51CTO技术栈公众号