設為首頁收藏本站

艾歐踢論壇

 找回密碼
 立即註冊

QQ登錄

只需一步,快速開始

搜索
熱搜: 活動 交友 discuz
查看: 511|回復: 0
打印 上一主題 下一主題

7 Steps To Room

[複製鏈接]
跳轉到指定樓層
樓主
發表於 2020-4-28 02:11:35 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
Step 1 — Update the gradle dependencies
Room’s dependencies are available via Google’s new Maven repository, simply add it to the list of repositories in your main build.gradle file:
  1. allprojects {
  2.     repositories {
  3.         google()
  4.         jcenter()
  5.     }
  6. }
複製代碼

Define your Room library version in the same file. For now, it’s in alpha, but keep an eye on our developer pages for version updates.
  1. ext {
  2.    ...
  3.     roomVersion = '1.0.0-alpha4'
  4. }
複製代碼

In your app/build.gradle file, add the dependencies for Room.
  1. dependencies{

  2. implementation        
  3.    “android.arch.persistence.room:runtime:$rootProject.roomVersion”
  4. annotationProcessor
  5.    “android.arch.persistence.room:compiler:$rootProject.roomVersion”
  6. androidTestImplementation
  7.    “android.arch.persistence.room:testing:$rootProject.roomVersion”
  8. }
複製代碼

To migrate to Room we will need to increase the database version and, in order to preserve user data, we will need to implement a Migration class. To test the migration, we need to export the schema. For that, add the following to your app/build.gradle file:
  1. android {
  2.     defaultConfig {
  3.         ...
  4.        // used by Room, to test migrations
  5.         javaCompileOptions {
  6.             annotationProcessorOptions {
  7.                 arguments = ["room.schemaLocation":
  8.                                  "$projectDir/schemas".toString()]
  9.             }
  10.         }
  11.     }

  12.     // used by Room, to test migrations
  13.     sourceSets {
  14.         androidTest.assets.srcDirs +=
  15.                            files("$projectDir/schemas".toString())
  16.     }
  17. ...
複製代碼


Step 2 — Update model classes to entities
Room creates a table for each class annotated with @Entity; the fields in the class correspond to columns in the table. Therefore, the entity classes tend to be small model classes that don’t contain any logic. Our User class represents the model for the data in the database. So let’s update it to tell Room that it should create a table based on this class:
Annotate the class with @Entity and use the tableName property to set the name of the table.
Set the primary key by adding the @PrimaryKey annotation to the correct fields — in our case, this is the ID of the User.
Set the name of the columns for the class fields using the @ColumnInfo(name = “column_name”) annotation. Feel free to skip this step if your fields already have the correct column name.
If multiple constructors are suitable, add the @Ignore annotation to tell Room which should be used and which not.

  1. @Entity(tableName = "users")
  2. public class User {

  3.     @PrimaryKey
  4.     @ColumnInfo(name = "userid")
  5.     private String mId;

  6.     @ColumnInfo(name = "username")
  7.     private String mUserName;

  8.     @ColumnInfo(name = "last_update")
  9.     private Date mDate;

  10.     @Ignore
  11.     public User(String userName) {
  12.         mId = UUID.randomUUID().toString();
  13.         mUserName = userName;
  14.         mDate = new Date(System.currentTimeMillis());
  15.     }

  16.     public User(String id, String userName, Date date) {
  17.         this.mId = id;
  18.         this.mUserName = userName;
  19.         this.mDate = date;
  20.     }
  21. ...
  22. }
複製代碼

Note: For a seamless migration, pay close attention to the tables and columns names in your initial implementation and make sure you’re correctly setting them in the @Entity and @ColumnInfo annotations.

Step 3 — Create Data Access Objects (DAOs)
DAOs are responsible for defining the methods that access the database. In the initial SQLite implementation of our project, all the queries to the database were done in the LocalUserDataSource file, where we were working with Cursor objects. With Room, we don’t need all the Cursor related code and can simply define our queries using annotations in the UserDao class.
For example, when querying the database for all users, Room does all the “heavy lifting” and we only need to write:
  1. @Query(“SELECT * FROM Users”)
  2. List<User> getUsers();
複製代碼


Step 4 — Create the database
So far, we have defined our Users table and its corresponding queries, but we haven’t yet created the database that brings these other pieces of Room together. To do this, we need to define an abstract class that extends RoomDatabase. This class is annotated with @Database, lists the entities contained in the database, and the DAOs which access them. The database version has to be increased by 1, from the initial value, so in our case, it will be 2.
  1. @Database(entities = {User.class}, version = 2)
  2. @TypeConverters(DateConverter.class)
  3. public abstract class UsersDatabase extends RoomDatabase {

  4.     private static UsersDatabase INSTANCE;

  5.     public abstract UserDao userDao();
複製代碼


Because we want to keep the user data, we need to implement a Migration class, telling Room what it should do when migrating from version 1 to 2. In our case, because the database schema isn’t altered, we will just provide an empty implementation:
  1. static final Migration MIGRATION_1_2 = new Migration(1, 2) {
  2.     @Override
  3.     public void migrate(SupportSQLiteDatabase database) {
  4. // Since we didn't alter the table, there's nothing else to do here.
  5.     }
  6. };
複製代碼


Create the database object in the UsersDatabase class, defining the database name and the migration:
  1. database = Room.databaseBuilder(context.getApplicationContext(),
  2.         UsersDatabase.class, "Sample.db")
  3.         .addMigrations(MIGRATION_1_2)
  4.         .build();
複製代碼


To find out more about how to implement database migrations and how they work under the hood, check out this post:
https://medium.com/google-develo ... h-room-f01e04b07929

Step 5 — Update the Repository to use Room
We’ve created our database, our Users table, and the queries, so now it’s time to use them! During this step, we’ll update the LocalUserDataSource class to use the UserDao methods. To do this, we’ll first update the constructor by removing the Context and adding UserDao. Of course, any class that instantiates LocalUserDataSource needs to be updated, too.
Second, we’ll update the LocalUserDataSource methods that query the database with calls to UserDao methods. For example, the method that fetches all users now looks like this:
  1. public List<User> getUsers() {
  2.    return mUserDao.getUsers();
  3. }
複製代碼


And now: run time!
One of the best features of Room is that if you’re executing your database operations on the main thread, your app will crash, and the following exception message is shown:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

One reliable way to move I/O operations off the main thread, is to create a new Runnable that runs on a single thread Executor for every database query. As we’re already using this approach in the sqlite flavor, no changes were needed.

Step 6 — On-device testing
We’ve created new classes — UserDao and UsersDatabase, and have modified our LocalUserDataSource to use the Room database. Now, we need to test them!
Testing UserDao
To test the UserDao, we need to create an AndroidJUnit4 test class. An awesome feature of Room is it’s ability to create an in-memory database. This avoids the need to clean up after every test case.
  1. @Before
  2. public void initDb() throws Exception {
  3.     mDatabase = Room.inMemoryDatabaseBuilder(
  4.                            InstrumentationRegistry.getContext(),
  5.                            UsersDatabase.class)
  6.                     .build();
  7. }
複製代碼


We also need to make sure we’re closing the database connection after each test.

  1. @After
  2. public void closeDb() throws Exception {
  3.     mDatabase.close();
  4. }
複製代碼


To test the insertion of a User, for example, we will insert the user and then we will check that we can indeed get that User from the database.

  1. @Test
  2. public void insertAndGetUser() {
  3.     // When inserting a new user in the data source
  4.     mDatabase.userDao().insertUser(USER);

  5.     //The user can be retrieved
  6.     List<User> users = mDatabase.userDao().getUsers();
  7.     assertThat(users.size(), is(1));
  8.     User dbUser = users.get(0);
  9.     assertEquals(dbUser.getId(), USER.getId());
  10.     assertEquals(dbUser.getUserName(), USER.getUserName());
  11. }
複製代碼


Testing the UserDao usage in LocalUserDataSource
Making sure that LocalUserDataSource still works correctly is easy, since we already have tests that cover the behavior of this class. All we need to do is create an in-memory database, acquire a UserDao object from it, and use it as a parameter for the LocalUserDataSource constructor.
  1. @Before
  2. public void initDb() throws Exception {
  3.     mDatabase = Room.inMemoryDatabaseBuilder(
  4.                            InstrumentationRegistry.getContext(),
  5.                            UsersDatabase.class)
  6.                     .build();
  7.     mDataSource = new LocalUserDataSource(mDatabase.userDao());
  8. }
複製代碼


Again, we need to make sure that we close the database after every test.

Testing the database migration
We discussed in detail how to implement database migration tests together with an explanation of how the MigrationTestHelper works in this blog post:
https://medium.com/google-develo ... ations-be93cdb0d975

Check out the code from the migration sample app for a more extensive example.

Step 7 — Cleanup
Remove any unused classes or lines of code that are now replaced by Room functionality. In our project, we just had to delete the UsersDbHelper class, that was extending the SQLiteOpenHelper class.


If you have a larger, more complex database and you want to incrementally migrate to Room, here’s how:
https://medium.com/google-develo ... o-room-66c2f655b377


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 轉播轉播 分享分享 分享淘帖
回復

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

小黑屋|Archiver|手機版|艾歐踢創新工坊    

GMT+8, 2024-6-10 23:56 , Processed in 0.281837 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表