使用 Room Database 简化Android本地数据库开发

使用Android中的Sqlite存储数据 中,演示了如何通过 android 原生的 api 来访问 sqlite 数据库,可以看到整个操作时比较麻烦的。现在Android官方推出了 Room Database, 在传统的 sqlite api 和面向对象之间架起了一座桥梁,简化了开发,提高了开发效率。

总体架构

先上一张官方的架构图:

Room Database架构图

从架构图可以看到,Room Database 其实时一个在 SQLite 和 业务,UI程序之间的要给薄层,为应用程序提供了简洁,规范的本地数据库访问方式。其核心是三个类型:

  1. Entities - 所谓 Entities 指的就是业务对象实体(数据)对象。通常与数据表一一对应。或者叫数据库中的表在内存中的映像。类的每一个实例(对象)与表中的记录相对应。
  2. Data Access Object - 也叫 DAO, 数据访问对象,用来封装所有对数据库的操作(CURD - 增、删、查、改)。
  3. Room Database - 与数据库对应,所有的 Entitiy, DAO 将被对应的 Room Database 管理。

如果你熟悉 Java 后端的开发,就知道这套东西有点像 Java 后端的 ORM 方案。

下面,就以 使用Android中的Sqlite存储数据 待办事项案例来演示如何使用 Room Database

配置 Room Database

要使用 Room Database, 首先需要在项目中增加一些依赖项。 打开项目中 app 模块的 build.gradle 文件,在 dependencies 中增加以下内容:

1
2
implementation 'android.arch.persistence.room:runtime:1.1.1'
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'

定义实体(Entity)类

定义一个待办事项的实体类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Data
@NoArgsConstructor
@Entity(tableName = "tbl_todo")
public class Todo {

@PrimaryKey(autoGenerate = true)
@NonNull
private int id;

@ColumnInfo(name = "title")
private String title;

@ColumnInfo(name = "description")
private String desc;

@ColumnInfo(name = "done")
private Boolean done;
}

类定义本身很简单,主要是使用了一些注解:

Entity - 注解用来标识一个实体类并指明其对应的表名
PrimaryKey - 注解用来标识该属性是对应表中的主键,并设置为自动生成。
ColumnInfo - 用来声明一些表中附加的列信息

以上三个是 Room Database 中提供的注解。

在例子中,为了减少 get / set 等方法的书写,也使用了 lombok 库,如果不熟悉在 android 中使用 Lombok 库,可以参考 在Android开发中使用 Lombok 库

定义 DAO

通常每个实体类需要有一个对应的DAO, 因为我们为 Todo 类定义一个 TodoDao。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Dao
public interface TodoDao {

@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Todo todo);

@Update
void update(Todo todo);

@Delete
void delete(Todo todo);

@Query("select * from tbl_todo")
List<Todo> findAll();
}

可以看到,我们其实定义的是一个接口(interface), 因为不需要写具体的实现。 增、删、查、改 四个操作,分别用四个注解来标准。最方便的是可以直接写 SQL 语句(需要满足SQLite支持的SQL级别)。 注意:SQL语句中对应的是表明,不是类的名称,这点和一些Java中的ORM库不同

定义数据库类

需要定义一个数据库类来管理实体类,DAO类,该类继承于 RoomDatabase,并且是要给抽象类。

1
2
3
4
5
@Database(entities = {Todo.class}, version = 1, exportSchema = false)
public abstract class DatabaseHelper extends RoomDatabase {

public abstract TodoDao todoDao();
}

在应用中使用 Room Database

构建完实体(Entity), DAO 和 数据库类以后,就可以在应用中使用了。首先,需要调用 Room 的 databaseBuilder 函数,构造数据库类的实例:

1
databaseHelper = Room.databaseBuilder(getApplicationContext(), DatabaseHelper.class, "todo-db").allowMainThreadQueries().build();

其中 “todo-db” 是数据库名,也是数据库文件的名称。当然,在使用 Room Database 以后,通常不需要关心具体的文件名。

注意:在示例代码中,调用了 allowMainThreadQueries 方法,使我们可以在主线程(UI现成)中操作数据库,对于很简单的应用可以这样使用,对于复杂的应用,这样可能会导致长时间的数据库操作影响界面的响应,造成不好的用户体验。所以 Room Database 是不允许在主线程中使用的。

后续的一些文章会介绍如何异步使用 Room Database。本文先聚焦于 Room Database 的基础操作。

下面是完整的示例代码,演示在一个 Activity 中,通过两个按钮分别触发新增和查询功能。

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
public class RoomDatabaseActivity extends AppCompatActivity {

private static final String TAG = RoomDatabaseActivity.class.getSimpleName();

private DatabaseHelper databaseHelper;
private TodoDao todoDao;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_room_database);

ButterKnife.bind(this);
databaseHelper = Room.databaseBuilder(getApplicationContext(), DatabaseHelper.class, "todo-db").allowMainThreadQueries().build();
todoDao = databaseHelper.todoDao();
}

@OnClick(R.id.btnInsert) void onInsert() {

Todo todo = new Todo();
todo.setTitle("task1");
todo.setDesc("Description for task1");
todo.setDone(false);
todoDao.insert(todo);
}

@OnClick(R.id.btnQuery) void onQuery() {

List<Todo> list = todoDao.findAll();
list.forEach(todo -> {
Log.d(TAG, "todo = " + todo);
});
}
}

本文标题:使用 Room Database 简化Android本地数据库开发

文章作者:晨星

发布时间:2019年08月13日 - 11:08

最后更新:2020年05月28日 - 16:05

原始链接:https://www.mls-tech.info/app/android/android-room-database/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。