7 Steps To Room
Bài đăng này đã không được cập nhật trong 7 năm
Room là 1 thư viện nằm trong Android Architecture Components. Nó giúp các lập trình viên thao thao tác dễ dàng hơn với SQLiteDatabase
trong ứng dụng của mình. Giảm thiểu số lượng mà lỗi, thừa và kiểm tra truy vấn lúc biên dịch chương trình.
Sau đây là 7 bước cơ bản để bạn có thể áp dụng ROOM
vào ứng dụng của mình.
Cập nhật lại Build Gradle, khởi tạo các
entities
,DAOs
vàdatabase
, thay thếSQLiteDatabase
bằng cách gọi các phương thức trongDAOs
, kiểm tra mọi thứ bạn khỏi tạo và xóa những class không cần thiết.
Trong demo này mình sẽ xây ứng dụng hiển thị và chỉnh sửa tên người dùng, lưu dữ liệu xuống database như kiểu là 1 User object
.
- sqlite: Sử dụng SQLiteOpenHelper và các giao thức SQLite truyền thống.
- room: Thay thế bằng
Room
và cung các giao thức truy vấn. Áp dụng mơ hìnhModel-View-Presenter
và làm việc với classUserRepository
.
Step 1 — Update the gradle dependencies.
Room’s dependencies
được cung cấp qua Maven repository
của Google’s
. Đơn giản là bạn chỉ cần thêm 1 vài khai báo vào trong build.gradle
chính của dự án.
allprojects {
repositories {
google()
jcenter()
}
}
ext {
...
roomVersion = '1.0.0-alpha4'
}
trong app/build.gradle
android {
defaultConfig {
...
// used by Room, to test migrations
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation":
"$projectDir/schemas".toString()]
}
}
}
// used by Room, to test migrations
sourceSets {
androidTest.assets.srcDirs +=
files("$projectDir/schemas".toString())
}
dependencies{
…
implementation "android.arch.persistence.room:runtime:$rootProject.roomVersion"
annotationProcessor "android.arch.persistence.room:compiler:$rootProject.roomVersion"
androidTestImplementation "android.arch.persistence.room:testing:$rootProject.roomVersion"
}
Step 2 — Update model classes to entities
Room
khỏi tạo các bảng thông qua annotated @Entity
. Các trường trong class là các cột trong bảng.
Annotate @Entity
sử dụngtableName
để định nghĩa tên của bảng.- Sử dụng
@PrimaryKey
để định nghĩa khóa chính của bảng. - Sử dụng
@ColumnInfo(name = “column_name”)
để định nghĩa tên các cột trong bảng. - Nếu có nhiều
constructors
thì các bạn thêm@Ignore
để khai báo cho Room biết là có sử dụngconstructors
này hay không.
@Entity(tableName = "users")
public class User {
@PrimaryKey
@ColumnInfo(name = "userid")
private String mId;
@ColumnInfo(name = "username")
private String mUserName;
@ColumnInfo(name = "last_update")
private Date mDate;
@Ignore
public User(String userName) {
mId = UUID.randomUUID().toString();
mUserName = userName;
mDate = new Date(System.currentTimeMillis());
}
public User(String id, String userName, Date date) {
this.mId = id;
this.mUserName = userName;
this.mDate = date;
}
...
}
Step 3 — Create Data Access Objects (DAOs)
DAOs
có trách nhiệm định nghĩa các phương trức giao tiếp với cơ sở dữ liệu. Trong mô hình sử dụng SQLite
truyền thống công việc này được thực hiện trong LocalUserDataSource
thông qua lớp Cursor
. Với Room
chúng ta không cần sử dụng Cursor
và đơn giản là định nghĩa các truy vấn sử dụng annotations
trong UserDao.class
.
@Query(“SELECT * FROM Users”)
List<User> getUsers();
Step 4 — Create the database
Bây giờ chúng ta đã định nghĩa bảng Users
nhưng chúng ta chưa khởi tạo database để chưa các bảng lại với nhau. Để làm việc này chúng ta sẽ định nghĩa 1 lớp trừu tượng (abstract class) kế thừa từ RoomDatabase
. Class này được định nghĩa với annotated @Database
chưa các danh sách thực thế trong database và các DAOs
liên quan đến chúng.
Với mỗi lần thay đổi class này thì chúng ta lại tăng version lên 1 như trong vd này tôi sẽ tăng vesion
của database lên thành 2.
@Database(entities = {User.class}, version = 2)
@TypeConverters(DateConverter.class)
public abstract class UsersDatabase extends RoomDatabase {
private static UsersDatabase INSTANCE;
public abstract UserDao userDao();
....
}
Bởi vì khi tăng version database lên thêm 1 nhưng vẫn muốn giữa lại database cũ nên chúng ta cần khai báo 1 lớp Migration
để nói với Room
những gì ta muốn giữ lại khi nâng từ version 1->2
.
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
// Since we didn't alter the table, there's nothing else to do here.
}
};
Trong class UsersDatabase này chúng ta sẽ định nghĩa tên và database và migration
chúng.
database = Room.databaseBuilder(context.getApplicationContext(),
UsersDatabase.class, "Sample.db")
.addMigrations(MIGRATION_1_2)
.build();
các bạn có thể tìm hiểu rõ hơn về migration
trong Room tại đây.
Step 5 — Update the Repository to use Room
Chúng ta đã khởi tạo Database, bảng User, và liên kết, truy vấn đến database và bây giờ là lúc chúng ta sủe dụng chúng.
Đầu tiên là chúng ta sẽ cập nhật file LocalUserDataSource
để sử dụng UserDao
. Việc đầu tiên là chung ta cần loại bỏ Context
và thêm UserDao
.
Bước tiếp theo chúng ta sẽ viết hàm truy vấn từ database
bằng cách gọi truy vấn từ UserDao
.
public List<User> getUsers() {
return mUserDao.getUsers();
}
Đến đây khi lần đầu chạy ứng dụng bạn sẽ bị Exception
là java.lang.IllegalStateException
khi bạn khỏi tạo, truy vấn dữ liệu trên main thread
. Bạn cần sử dụng các truy vấn ở 1 thread
khác bằng cách đơn giản nhất là sử dụng Runnable
.
Trong bài sau mình sẽ giới thiệu với các bạn các kết hợp Room với RxJava để truy vấn dữ liệu.
Step 6 — On-device testing
Testing UserDao
Để test UserDao
chúng ta cần khỏi tạo AndroidJUnit4
test class. Khả năng tuyệt vời của Room là chúng có thể tạo 1 lớp dữ liệu ngay trên bộ nhớ Ram. Điều này giúp chung ta không cần xóa dữ liệu test
trong cơ sở dữ liệu sau khi chạy các test case
.
@Before
public void initDb() throws Exception {
mDatabase = Room.inMemoryDatabaseBuilder(
InstrumentationRegistry.getContext(),
UsersDatabase.class)
.build();
}
....
@After
public void closeDb() throws Exception {
mDatabase.close();
}
Test khỏi tạo 1 User mới trong cơ sở dữ liệu và kiểm tra xem User đã được thêm mới thành công hay chưa.
@Test
public void insertAndGetUser() {
// When inserting a new user in the data source
mDatabase.userDao().insertUser(USER);
//The user can be retrieved
List<User> users = mDatabase.userDao().getUsers();
assertThat(users.size(), is(1));
User dbUser = users.get(0);
assertEquals(dbUser.getId(), USER.getId());
assertEquals(dbUser.getUserName(), USER.getUserName());
}
Testing the UserDao usage in LocalUserDataSource
@Before
public void initDb() throws Exception {
mDatabase = Room.inMemoryDatabaseBuilder(
InstrumentationRegistry.getContext(),
UsersDatabase.class)
.build();
mDataSource = new LocalUserDataSource(mDatabase.userDao());
}
Và cuối cùng hãy chắn ràng bãn đã đóng cơ sở dũ liệu sau khi truy vấn.
Step 7 — Cleanup
Loại bỏ tất cả các class không sử dụng và các chức năng được thay thế bằng Room
. Trong class chúng ta sẽ không sẻu dụng UsersDbHelper.class
và SQLiteOpenHelper.class
.
Việc sử dụng Room
kiếm việc kiểm soát mã lỗi dễ dàng hơn, các truy vấn được kiểm tra tại thời điểm biên dịch làm cho mọi mã lỗi đều có thể kiểm xoát được.
Một chương trình test thử về Room
bạn có thể tham khảo tại đây..
Bài viết được dịch từ: https://medium.com/google-developers/7-steps-to-room-27a5fe5f99b2.
All rights reserved