千里之行,始于足下


  • Home

  • Tags

  • Archives

  • Commonweal 404

使用 Room 引用复杂数据

Posted on 2020-01-09

Room 提供了在基元类型和盒装类型之间进行转换的功能,但不允许实体之间进行对象引用。本文档介绍了如何使用类型转换器,以及 Room 为何不支持对象引用。

使用类型转换器

有时,您的应用需要使用自定义数据类型,其中包含您想要存储到单个数据库列中的值。要为自定义类型添加此类支持,您需要提供一个TypeConverter,它可以在自定义类与 Room 可以保留的已知类型之间来回转换。

例如,如果我们想保留 Date 的实例,则可以编写以下 TypeConverter,将等效的 Unix 时间戳存储在数据库中:

1
2
3
4
5
6
7
8
9
10
11
public class Converters {
@TypeConverter
public static Date fromTimestamp(Long value) {
return value == null ? null : new Date(value);
}

@TypeConverter
public static Long dateToTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
Read more »

迁移 Room 数据库

Posted on 2020-01-09

当您在应用中添加和更改功能时,需要修改实体类以反映这些更改。当用户更新到您应用的最新版本时,您不想让他们丢失所有现有数据,尤其是在您无法从远程服务器恢复数据时。

借助 Room,您可以编写 Migration类,以这种方式保留用户数据。每个 Migration类均指定一个 startVersion和endVersion。在运行时,Room会运行每个Migration类的migrate()`方法,以按照正确的顺序将数据库迁移到更高版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, "
+ "`name` TEXT, PRIMARY KEY(`id`))");
}
};

static final Migration MIGRATION_2_3 = new Migration(2, 3) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE Book "
+ " ADD COLUMN pub_year INTEGER");
}
};

Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
.addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();

迁移过程完成后,Room 会验证架构以确保迁移正确进行。如果 Room 发现问题,则会抛出包含不匹配信息的异常。

Read more »

Room预填充数据库

Posted on 2020-01-07

有时,您可能希望您的应用程序从已经加载了一组特定数据的数据库开始,这称为预填充数据库。在Room2.2.0及更高版本中,可以使用API方法在初始化时使用设备文件系统中预打包的数据库文件中的内容预填充Room数据库。

注意:通过Room.inMemoryDatabaseBuilder()得到的数据库不支持使用createFromAsset()或createFromFile()预填充数据库。

Read more »

使用 Room DAO 访问数据

Posted on 2020-01-07

要使用 Room 访问应用的数据,您需要使用数据访问对象 (DAO)。这些Dao对象构成了Room的主要组件,因为每个DAO都包含一些方法,这些方法提供对应用数据库的抽象访问权限。

通过使用DAO类(而不是查询构建器或直接查询)访问数据库,您可以拆分数据库架构的不同组件。

DAO既可以是接口,也可以是抽象类。如果是抽象类,则该DAO可以选择有一个以RoomDatabase为唯一参数的构造函数,Room会在编译时创建每个DAO实现。

注意:除非您对构建器调用 allowMainThreadQueries(),否则 Room 不支持在主线程上访问数据库,因为它可能会长时间锁定界面。异步查询(返回 LiveData 或 Flowable 实例的查询)无需遵守此规则,因为此类查询会根据需要在后台线程上异步运行查询。

Read more »

Room定义对象之间的关系

Posted on 2020-01-07

由于 SQLite 是关系型数据库,因此您可以指定各个对象之间的关系。尽管大多数对象关系映射库都允许实体对象互相引用,但 Room 明确禁止这样做。

定义一对多关系

即使您不能使用直接关系,Room 仍允许您定义实体之间的外键约束。

例如,如果存在另一个名为 Book 的实体,您可以使用 @ForeignKey注释定义该实体与 User 实体的关系,如以下代码段所示:

1
2
3
4
5
6
7
8
9
10
@Entity(foreignKeys = @ForeignKey(entity = User.class,
parentColumns = "id",
childColumns = "user_id"))
public class Book {
@PrimaryKey public int bookId;

public String title;

@ColumnInfo(name = "user_id") public int userId;
}

由于零个或更多个 Book 实例可以通过 user_id 外键关联到一个 User 实例,因此这会在 User 和 Book 之间构建一对多关系模型。

外键非常强大,可让您指定引用的实体更新后会发生什么。例如,您可以通过在@ForeignKey注释中添加onDelete = CASCADE,在 User 的对应实例删除后告知 SQLite 删除该用户的所有图书。

注意:SQLite 将 @Insert(onConflict = REPLACE)作为一组 REMOVE 和 REPLACE 操作(而不是单个 UPDATE 操作)处理。这种替换冲突值的方法可能会影响您的外键约束。

Read more »

使用 Room 实体定义数据

Posted on 2020-01-07

使用 Room时,您可以将相关字段集定义为实体。对于每个实体,系统会在关联的 Database对象中创建一个表来存储这些项。您必须通过 Database类中的 entities数组引用实体类。

以下代码段展示了如何定义实体:

1
2
3
4
5
6
7
8
@Entity
public class User {
@PrimaryKey
public int id;

public String firstName;
public String lastName;
}

要保留某个字段,Room 必须拥有该字段的访问权限。您可以将某个字段设为public,也可以为其提供 getter 和 setter。

Read more »

Jetpack WorkManager

Posted on 2020-01-07

Jetpack Paging

Posted on 2020-01-07

Jetpack Navigation

Posted on 2020-01-07

Room概览

Posted on 2020-01-07

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

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

Read more »
12

Victor.yin

静思笃行,持中秉正

13 posts
5 tags
© 2020 Victor.yin
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4
粤ICP备18095074号