Room系列专题
Android Jetpack之Room篇
Room Entity注解说明
Room Dao注解说明
Room Fts 虚拟表模块
Room DatabaseView 视图
Room SkipQueryVerification
Room TypeConverter 属性类型转换器
引用
1
2
3
4
5
6
7
8
9
10
|
// Room components
implementation "androidx.room:room-runtime:2.2.0-rc01"
annotationProcessor "androidx.room:room-compiler:2.2.0-rc01"
// kotlin扩展和协程支持
implementation "androidx.room:room-ktx:2.2.0-rc01"
//RxJava 支持库
implementation "androidx.room:room-rxjava2:2.2.0-rc01"
// 可选 - Guava 的支持库
implementation "androidx.room:room-guava:2.2.0-rc01"
|
基本使用
Room 主要包含三个组件:
- Database: 包含数据库持有者,作为与应用持久化相关数据的底层连接的主要接入点。这个类需要用 @Database 注解,并满足下面条件:
- 必须是继承 RoomDatabase 的抽象类
- 注解中包含该数据库相关的实体类列表
- 包含的抽象方法不能有参数,且返回值必须是被 @Dao 注解的类
- Entity: 表示了数据库中的一张表
- DAO: 包含了访问数据库的一系列方法

简单使用流程
0.配置编译器选项
如果不配置,编译就会报错。
Room具有以下注释处理器选项:
- room.schemaLocation:配置并启用将数据库模式导出到给定目录中的JSON文件中。
- room.incremental:启用Gradle增量注释处理器。
- room.expandProjection:将Room配置为重写查询,以使其顶部的星形投影扩展为仅包含DAO方法返回类型中定义的列。
代码配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [
"room.schemaLocation":"$projectDir/schemas".toString(),
"room.incremental":"true",
"room.expandProjection":"true"]
}
}
}
}
|
1.创建模型类
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
|
@Entity(tableName = "users")
public class User {
@NonNull
@PrimaryKey//每个bean类都必须要声明一个主键,除非父类声明了。
@ColumnInfo(name = "userid")
private String mId;
@ColumnInfo(name = "username")
private String mUserName;
@Ignore
public User(String userName) {
mId = UUID.randomUUID().toString();
mUserName = userName;
}
public User(String id, String userName) {
this.mId = id;
this.mUserName = userName;
}
public String getId() {
return mId;
}
public String getUserName() {
return mUserName;
}
}
|
2.Dao添加 @Dao 注解,然后在方法中添加注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Dao
public interface UserDao {
//查询数据
@Query("SELECT * FROM Users LIMIT 1")
Flowable<User> getUser();
//插入数据
@Insert(onConflict = OnConflictStrategy.REPLACE)
Completable insertUser(User user);
//删除数据
@Query("DELETE FROM Users")
void deleteAllUsers();
}
|
3.创建类继承 RoomDatabase ,entities 填写需要的类,然后写抽象方法获取 Dao.
1
2
3
4
5
6
7
8
|
/**
* 必须是 RoomDatabase 的抽象类
*/
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
//...code
}
|
4.创建数据库,并单例
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
|
/**
* 必须是 RoomDatabase 的抽象类
*/
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
private static volatile AppDatabase INSTANCE;
public static AppDatabase getInstance(Context context) {
if (INSTANCE == null) {
synchronized (AppDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, "Sample.db")
.build();
}
}
}
return INSTANCE;
}
public static UserDao getUserDao(Context context) {
return getInstance(context).userDao();
}
}
|
5.使用
1
|
AppDatabase.getUserDao(context).insertUser(new User("zhang"));
|
参数
addMigrations()升级数据库
1
2
3
4
5
6
7
8
9
10
|
private Migration migration_1_2 = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("");
}
};
Room.databaseBuilder(context,AppDatabase.class, "database-name")
.addMigrations(migration_1_2)//升级数据库
.build();
|
enableMultiInstanceInvalidation()
设置此 RoomDatabase 实例中的表失效是否应该广播,并与相同 RoomDatabase 的其他实例(包括单独进程中的实例)同步。为了防止启用多实例失效,必须在两端同时启用。
默认情况下不启用此功能。
这不适用于内存数据库。这在针对不同数据库文件的数据库实例之间不起作用。
addCallback()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
.addCallback(new RoomDatabase.Callback() {
//第一次创建数据库时调用。在创建所有表之后调用这个函数。
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
}
//在数据库打开时调用。
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
}
//在数据库被破坏性迁移后调用
@Override
public void onDestructiveMigration(@NonNull SupportSQLiteDatabase db) {
}
})
|
createFromFile() createFromAsset()
配置Room以使用预打包的数据库文件创建和打开数据库
setTransactionExecutor()
设置事务的线程处理器,默认是固定 4 大小的ExecutorService。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public class DefaultTaskExecutor extends TaskExecutor {
private final Object mLock = new Object();
private final ExecutorService mDiskIO = Executors.newFixedThreadPool(4, new ThreadFactory() {
private static final String THREAD_NAME_STEM = "arch_disk_io_%d";
private final AtomicInteger mThreadId = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName(String.format(THREAD_NAME_STEM, mThreadId.getAndIncrement()));
return t;
}
});
//...code
}
|
setQueryExecutor()
设置查询操作的线程处理器
setJournalMode
设置此数据库的日志模式。
1
2
3
4
5
6
7
8
9
10
|
public enum JournalMode {
//让room选择日志模式。这是未指定显式值时的默认值。
//当设备运行的API级别低于16或它是一个低ram设备时,实际值将是 TRUNCATE 。否则,将使用 WRITE_AHEAD_LOGGING。
AUTOMATIC,
//截断日志模式
TRUNCATE,
//写前日志记录模式
@RequiresApi(Build.VERSION_CODES.JELLY_BEAN)
WRITE_AHEAD_LOGGING;
}
|
allowMainThreadQueries() 允许在主线程查询数据
建议禁用 room 的主线程查询检查。
Room确保数据库不会在主线程上被访问,因为它可能会锁定主线程并触发ANR。如果需要从主线程访问数据库,应该始终使用异步替代方法,或者手动将调用移动到后台线程。
您可能需要关闭此复选框以进行测试。
openHelperFactory()
设置数据库工厂。如果想使用第三库数据的时候,可以自定设置。
fallbackToDestructiveMigration()
允许空间破坏性地重新创建数据库表
加上它之后升级就会清空数据库中以前的数据。一般情况下我们都是希望保留数据的,所以需要些我们自己的Migration类,定义升级的sql。
fallbackToDestructiveMigrationOnDowngrade()
当降级到旧模式版本时,如果迁移不可用,则允许Room破坏性地重新创建数据库表。
fallbackToDestructiveMigrationFrom(int…)
通知Room允许从特定的启动模式版本破坏性地重新创建数据库表。
和LiveData一起使用
添加依赖
1
2
3
4
5
6
7
8
9
10
|
//lifecycle依赖
implementation "androidx.lifecycle:lifecycle-runtime:2.2.0-alpha04"
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0-alpha04"
implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0-alpha04"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0-alpha04"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-alpha04"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0-alpha04"
// ReactiveStreams support for LiveData
implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:2.1.0"
|
修改返回类型
1
2
3
4
5
|
@Dao
public interface MyDao {
@Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
public LiveData<List<User>> loadUsersFromRegionsSync(List<String> regions);
}
|
和RxJava一起使用
添加依赖
1
2
|
// RxJava support for Room
implementation "androidx.room:room-rxjava2:2.2.0-rc01"
|
修改返回类型
1
2
3
4
5
|
@Dao
public interface MyDao {
@Query("SELECT * from user where id = :id LIMIT 1")
public Flowable<User> loadUserById(int id);
}
|
直接游标访问
1
2
3
4
5
|
@Dao
public interface MyDao {
@Query("SELECT * FROM user WHERE age > :minAge LIMIT 5")
public Cursor loadRawUsersOlderThan(int minAge);
}
|
如果你喜欢我的文章,可以关注我的掘金、公众号、博客、简书或者Github!
简书: https://www.jianshu.com/u/a2591ab8eed2
GitHub: https://github.com/bugyun
Blog: https://ruoyun.vip
掘金: https://juejin.im/user/56cbef3b816dfa0059e330a8/posts
CSDN: https://blog.csdn.net/zxloveooo
欢迎关注微信公众号
