The original link

preface

Android provides SQLite database for data persistence, and provides corresponding API to access the database, while Room framework provides SQLite data access abstraction layer, which brings convenience to efficient database access layer

The APP can cache user data, read data from SQLite when the APP is offline, and complete data synchronization with the server when the connection is reconnected

Google strongly recommends using the Room framework for SQLite databases

Hello World

Start by adding the necessary dependencies in build.gradle

dependencies {
    def room_version = 1.1.1 ""

    implementation "android.arch.persistence.room:runtime:$room_version"
    annotationProcessor "android.arch.persistence.room:compiler:$room_version" // use kapt for Kotlin

    // optional - RxJava support for Room
    implementation "android.arch.persistence.room:rxjava2:$room_version"

    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "android.arch.persistence.room:guava:$room_version"

    // Test helpers
    testImplementation "android.arch.persistence.room:testing:$room_version"
}
Copy the code

Create an Entity class User where @entity represents a table in the database and the name attribute behind @ColumnInfo corresponds to a field name in the database. Implement Getter and Setter methods for the Entity class

@Entity
public class User {
    @PrimaryKey
    private int uid;

    @ColumnInfo(name = "first_name")
    private String firstName;

    @ColumnInfo(name = "last_name")
    private String lastName;

    public int getUid(a) {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getFirstName(a) {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName(a) {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Override
    public String toString(a) {
        return "User{" +
                "uid=" + uid +
                ", firstName='" + firstName + '\' ' +
                ", lastName='" + lastName + '\' ' +
                '} '; }}Copy the code

The dao layer corresponding to entity class UserDao was created, and the CRUD interface definition of User was completed. The @DAO annotation defined a DAO layer, and the parameter was assigned (passed) using the method of clumn_name


@Dao
public interface UserDao {
    @Query("SELECT * FROM user")
    List<User> getAll(a);

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    List<User> loadAllByIds(int[] userIds);

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND "
            + "last_name LIKE :last LIMIT 1")
    User findByName(String first, String last);

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertAll(User... users);

    @Delete
    void delete(User user);
}
Copy the code

Create AppDatabase with the @Database annotation indicating that this is a Database action class, entities correspond to Entity Entity class, version is used for Database version upgrades, and define an abstract method in this abstract class that returns the DAO layer

@Database(entities = {User.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao(a);
}
Copy the code

Initialize AppDatabase, the instance object used to operate the database. Do not initialize it in the main thread. You must start a new thread to initialize it

new Thread(new Runnable() {
    @Override
    public void run(a) {
        AppDatabase db = Room.databaseBuilder(getApplicationContext(),
                AppDatabase.class, "database-name").build();
    }
}).start();
Copy the code

test

You can also pass an array of users


for (int i = 0; i < 10; i++) {
    User user = new User();
    user.setUid(i);
    user.setFirstName("Shell" + i);
    user.setLastName("Hub" + i);
    insertAll(db, user);
}
Copy the code

If the following error, modify the dao layer annotated as @ Insert (onConflict = OnConflictStrategy. REPLACE)

android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: User.uid (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY)
Copy the code

Query all data

for (User user : db.userDao().getAll()) {
    System.out.println(user);
}
Copy the code

other…

Room singleton mode

It is best to use the singleton schema in design mode to get the database instance, since it is time consuming and memory consuming to get the database instance each time. We can define a custom class to inherit Application and define a public static method to get the database instance


public class App extends Application {
    private static Context context;
    private static final String DATABASE_NAME = "SHELLHUB";
    private static AppDatabase DB_INSTANCE;
    @Override
    public void onCreate(a) {
        super.onCreate();
        context = getApplicationContext();

        new Thread(new Runnable() {
            @Override
            public void run(a) {
                DB_INSTANCE = Room.databaseBuilder(getApplicationContext(),
                        AppDatabase.class, DATABASE_NAME).build();

            }
        }).start();
    }

    public static AppDatabase getDB(a) {
        returnDB_INSTANCE; }}Copy the code