Room 是 Jetpack 中用于创建、存储和管理由 SQLite 数据库支持的持久性数据的组件。
Room 在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库。
处理大量结构化数据的应用可极大地受益于在本地保留这些数据。最常见的用例是缓存相关数据。
这样,当设备无法访问网络时,用户仍可在离线状态下浏览相应内容。
设备重新连接到网络后,用户发起的所有内容更改都会同步到服务器。
官方建议使用 Room,而不是 SQLite 。
官网说明镇楼 https://developer.android.google.cn/training/data-storage/room#db-migration-testing
Room 包含 3 个主要组件:
- 数据库:包含数据库持有者,并作为应用已保留的持久关系型数据的底层连接的主要接入点。
使用 @Database 注释的类应满足以下条件:
- 是扩展 RoomDatabase 的抽象类。
- 在注释中添加与数据库关联的实体列表。
- 包含具有 0 个参数且返回使用 @Dao 注释的类的抽象方法。
- 在运行时,您可以通过调用
Room.databaseBuilder()
或Room.inMemoryDatabaseBuilder()
获取 Database 的实例。
- Entity:表示数据库中的表。
- DAO:包含用于访问数据库的方法。
应用使用 Room 数据库来获取与该数据库关联的数据访问对象 (DAO)。
然后,应用使用每个 DAO 从数据库中获取实体,然后再将对这些实体的所有更改保存回数据库中。
最后,应用使用实体来获取和设置与数据库中的表列相对应的值
开始使用。
1.引入依赖支持
在 app 的 build.gradle 中添加如下,
dependencies {
def room_version = "2.2.6"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
// optional - RxJava support for Room
implementation "androidx.room:room-rxjava2:$room_version"
// optional - Guava support for Room, including Optional and ListenableFuture
implementation "androidx.room:room-guava:$room_version"
// optional - Test helpers
testImplementation "androidx.room:room-testing:$room_version"
}
同时在这个文件的 android{ }
闭包的 defaultConfig { }
中添加如下,
添加后,操作数据库会在 $projectDir/schemas
目录下生成 json 文件。
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments += [
"room.schemaLocation":"$projectDir/schemas".toString(),
"room.incremental":"true",
"room.expandProjection":"true"]
}
}
}
}
2.创建实体数据类 Entity
所谓实体数据类,就是我们存储的数据,一般就是 JavaBean 对象。
以 User 为例,包含3个参数,uid 、firstName、lastName ,uid 作为主键。
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity
public class User {
@PrimaryKey(autoGenerate = true)
public int uid;
@ColumnInfo(name = "firstName")
public String firstName;
@ColumnInfo(name = "lastName")
public String lastName;
@NonNull
@Override
public String toString() {
return String.format("User{uid:%d, firstName:%s, lastName:%s}", uid, firstName, lastName);
}
}
3.创建访问数据库的方法 UserDao
创建一个接口 UserDao,定义需要用到的方法。
访问数据库,一般就是增删改查。
顺便复习下数据库语法。
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import java.util.List;
@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 firstName LIKE :first AND lastName LIKE :last")
User findByName(String first, String last);
@Insert
void insertUser(User... users);
@Delete
void deleteUser(User user);
}
tip:对应的注解,导入依赖后可以代码补全,很方便。
4.继承并实现RoomDatabase
注解 @Database(entities = {User.class}, version = 1)
的意思是,数据类是 User 类,版本号是 1 。
import androidx.room.Database;
import androidx.room.RoomDatabase;
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
5.使用
获取到 4 中的实例后,就可以通过 UserDao
访问数据库了。
为了方便,直接在 Activity 的 onCreate 中操作。allowMainThreadQueries()
表示允许在主线程操作,不添加的话会报错提示不能在主线程操作。
实际使用还是建议在子线程进行操作(如 Handler ),避免主线程堵塞。
AppDatabase db = Room.databaseBuilder(
getApplicationContext(),
AppDatabase.class,
"database-name")
.allowMainThreadQueries()//允许在主线程操作
.fallbackToDestructiveMigration()
.build();
User kuser = new User();
kuser.uid = 35;
kuser.firstName = "Kevin";
kuser.lastName = "Durant";
final User luser = new User();
luser.uid = 23;
luser.firstName = "LeBron";
luser.lastName = "James";
//添加数据
db.userDao().insertUser(kuser);
db.userDao().insertUser(luser);
//查询数据
List<User> v1 = db.userDao().getAll();
if (v1 != null) {
Log.d("luoah", "[MainActivity] -- onCreate -- v1:" + v1);
}
//删除数据
User foundUser = db.userDao().findByName("LeBron","James");
Log.d("luoah", "[MainActivity] -- onCreate -- foundUser:" + foundUser.toString());
db.userDao().deleteUser(foundUser);
List<User> v2 = db.userDao().getAll();
if (v2 != null) {
Log.d("luoah", "[MainActivity] -- onCreate -- v2:" + v2);
}
运行 log :
D/luoah: [MainActivity] -- onCreate -- v1:[User{uid:23, firstName:LeBron, lastName:James}, User{uid:35, firstName:Kevin, lastName:Durant}]
D/luoah: [MainActivity] -- onCreate -- foundUser:User{uid:23, firstName:LeBron, lastName:James}
D/luoah: [MainActivity] -- onCreate -- v2:[User{uid:35, firstName:Kevin, lastName:Durant}]