Android Room 简单使用

Table of Contents

1 Android Room 简单使用

1.1 说明

这次没有用内置的 SQLite 库,而是直接使用了 Room ,原因之一是 SQLite 在创建数据库的时候出错了,排查不到哪一步出错
二是这个 RoomFlutter 中的 floor 框架非常相似,可以无缝迁移

1.2 添加依赖

src/build.gradle

dependencies {
    def room_version = "2.4.2"
    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"
}

1.3 配置类

Room 包含三个主要组件

  • 数据库类
  • 数据实体
  • 数据访问对象(DAO)

他们的定义如下

1.3.1 数据实体

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

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

    @ColumnInfo(name = "last_name")
    public String lastName;
}

1.3.2 数据访问对象

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

    @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
    void insertAll(User... users);

    @Delete
    void delete(User user);
}

注意

  • 他只需要一个接口来表示 DAO 类型,代码会自动生成,不需要担心
  • 变量名替换用冒号 :

1.3.3 数据库类

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
}

1.4 投入使用

这里不使用官方教程提供的实例,而是

AppDatabase database = Room.databaseBuilder(
                getApplicationContext(),
                AppDatabase.class,
                "test.db")
                .allowMainThreadQueries().build();

UserDao userDao = database.userDao();

不知道为什么,直接使用 build 方法会产生错误,需要添加一个 allowMainThreadQueries
另外我们添加了一个 ButtonTextView 来实现一些交互,简单来说,按钮来添加数据, TextView 来显示数据

Button button = findViewById(R.id.button_add);
TextView textView = findViewById(R.id.textView);
button.setOnClickListener(view -> {
        userDao.insertAll(
                          new User(1, "hello", "world"),
                          new User(2, "fuck", "you"),
                          new User(3, "holy", "shit")
                          );

        List<User> users = userDao.getAll();
        textView.setText(users.stream().map(x -> x.toString()).collect(Collectors.joining("\n")));
    });

别忘了给 User 添加构造函数

现在问题来了,第一次点击按钮是没有问题的,第二次点击就会出错
这是因为数据库主键重复了,我们重新设置下数据模型类

@Entity
public class User {
    @PrimaryKey(autoGenerate = true)
    public Integer uid;

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

    @ColumnInfo(name = "last_name")
    public String lastName;
}

floor 框架一样,将主键的值设为 null ,程序会在数据库中自动添加主键,这样以后修改关于添加的代码

button.setOnClickListener(view -> {
        userDao.insertAll(
                          new User("hello", "world"),
                          new User("fuck", "you"),
                          new User("holy", "shit")
                          );

        List<User> users = userDao.getAll();
        textView.setText(users.stream().map(x -> x.toString()).collect(Collectors.joining("\n")));
    });

再次运行你会发现 又出错了 ,错误有关数据库迁移 Migration
这时因为原来的数据表有更改,需要修改原来的数据来兼容现有的数据库版本,这里我们简单处理,直接删掉重建一个
在创建数据库时

AppDatabase database = Room.databaseBuilder(
        getApplicationContext(),
        AppDatabase.class,
        "test.db")
        .fallbackToDestructiveMigration()
        .allowMainThreadQueries().build();

Author: Steiner

Created: 2022-03-04 五 16:01

Validate