Android -- 学习使用Jetpack组件Room

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}]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值