当前位置: 代码迷 >> 综合 >> Android Jetpack -- Room篇
  详细解决方案

Android Jetpack -- Room篇

热度:48   发布时间:2023-11-22 10:11:14.0

RoomSQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库。

处理大量结构化数据的应用可极大地受益于在本地保留这些数据。最常见的用例是缓存相关数据。这样,当设备无法访问网络时,用户仍可在离线状态下浏览相应内容。设备重新连接到网络后,用户发起的所有内容更改都会同步到服务器。

由于 Room 负责处理这些问题,因此建议使用 Room(而不是 SQLite)

Room添加依赖如下:

  implementation "androidx.room:room-runtime:$room_version"annotationProcessor "androidx.room:room-compiler:$room_version" // Kotlin使用kaptimplementation "androidx.room:room-ktx:$room_version" // Room的kotlin扩展implementation "androidx.room:room-rxjava2:$room_version"// Room的RxJava扩展

Room的架构由以下(注解)组成:

  • 数据库(@DataBase):包含数据库持有者,并作为应用已保留的持久关系型数据的底层连接的主要接入点。使用 @Database 注释的类应满足以下条件:
    - 是扩展 RoomDatabase 的抽象类。
    - 在注释中添加与数据库关联的实体列表。
    - 包含具有 0 个参数且返回使用 @Dao 注释的类的抽象方法。
    在运行时,您可以通过调用 Room.databaseBuilder() 或 Room.inMemoryDatabaseBuilder() 获取 Database 的实例。
  • 实体(@Entity):表示数据库中的表。
  • DAO(@Dao):包含用于访问数据库的方法。

下面以官方文档的示意图来介绍
在这里插入图片描述
以下为官方示例:
User

    @Entitydata class User(@PrimaryKey val uid: Int,@ColumnInfo(name = "first_name") val firstName: String?,@ColumnInfo(name = "last_name") val lastName: String?)

创建了User表,@Entity表示为表Class,@PrimaryKey表示该属性为主键,@ColumnInfo表示当前行,name指明行名。

UserDao

    @Daointerface UserDao {
    @Query("SELECT * FROM user")fun getAll(): List<User>@Query("SELECT * FROM user WHERE uid IN (:userIds)")fun loadAllByIds(userIds: IntArray): List<User>@Query("SELECT * FROM user WHERE first_name LIKE :first AND " +"last_name LIKE :last LIMIT 1")fun findByName(first: String, last: String): User@Insertfun insertAll(vararg users: User)@Deletefun delete(user: User)}

@Dao注解表示对外暴露的数据库接口。
接口中函数的注解@Query执行查询操作,value写SQL 查询语句,SQL语法字符串采用大写,变量采用小写,”:“引用函数的参数,返回值根据结果而定,可返回LiveData或者配合RxJava扩展返回可订阅对象(Flowable, Maybe, Single, Completable),后面的@Insert,@Delete,@Update都一样。

AppDatabase

    @Database(entities = arrayOf(User::class), version = 1)abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao}

@Database表示数据库,里面的entities参数可指定表的Class,version指定版本号,等等,其他的可自行查看源码。
抽象类内部则是返回Dao的抽象方法。

最后创建数据库即可。

   val db = Room.databaseBuilder(applicationContext,AppDatabase::class.java, "database-name").build()

以上编译完成后,会生成UserDao_Impl文件,顾名思义便是UserDao接口的实现。

当然这只是最简单的用法,你也可以结合LiveData和Rxjava实现响应式的获取数据。

配合LiveData

        @Query("SELECT * FROM user WHERE uid IN (:userIds)")fun loadAllByIds(userIds: IntArray): LiveData<List<User>>

当数据库初始化或数据发生改变的时候会响应上面的方法,剩下的就是LiveData相关了,具体的操作可以了解下LiveData的使用方式。

配合Rxjava

与Rxjava配合比LiveData稍麻烦,但也无妨。
引入依赖:

implementation “androidx.room:room-rxjava2:$room_version”// Room的RxJava扩展

然后更改返回结果的类型:

        @Query("SELECT * FROM user WHERE uid IN (:userIds)")fun loadAllByIds(userIds: IntArray): Flowable<List<User>>

当然不只有Flowable一个返回类型,有以下几个:

  • Flowable:
    • 1.当所查询的表中无改值时或查询语句返回空时Flowable将不会发射数据,onNextonError也不会回调
    • 2.当查询到数据时回调onNext
    • 3.当数据库初始化时或者数据发生改变时自动发射数据回调onNext
  • Maybe:
    • 1.当查询结果返回空时回调onComplete
    • 2.当有结果时回调onSuccessonComplete
    • 3.在onComplete回调后如果数据发生更新,将不会响应
  • Single
    • 1.当查询结果为空时返回回调onError(EmptyResultSetException.class)
    • 2.当有结果时回调onSuccess
    • 3.在onComplete回调后如果数据发生更新,将不会响应

所有根据实际的场景选择合适的方法才是正确的使用方式。

  相关解决方案