android Jetpack应用实战(四)-Room

为什么要用ROOM 

对于Android 开发人员来说,其实对数据库操作是很不熟练的,要写一堆Sql,很是麻烦,于是出现了很多开源的库方便我们操作,为此google 官方提出了Room 的库,解决sqlite 封装问题,毕竟是google 的,后期肯定会持续维护的.

ROOM 使用架构

如何使用

1,添加gradle


    def room_version = "2.5.1"

    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"

    // optional - RxJava2 support for Room
    implementation "androidx.room:room-rxjava2:$room_version"

    // optional - RxJava3 support for Room
    implementation "androidx.room:room-rxjava3:$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"

    // optional - Paging 3 Integration
    implementation "androidx.room:room-paging:$room_version"

2,添加表格


@Entity(tableName = "book")
public class Book {

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id",typeAffinity = ColumnInfo.INTEGER)
    public int id;

    @ColumnInfo(name = "bookName",typeAffinity = ColumnInfo.TEXT)
    public String bookName;



    public Book(int id, String bookName) {
        this.id = id;
        this.bookName = bookName;
    }

    @Ignore
    public Book(String bookName) {
        this.bookName = bookName;
    }
}

对应的是上面的Entity,一个Entity 对应一个表格(本例例中是book),一个表格对应一个Dao

@Entity(tableName = "author")  改写自己的表名

@PrimaryKey(autoGenerate = true) 主键是否自增长

@ColumnInfo(name = "bookName",typeAffinity = ColumnInfo.TEXT)  分别对应字段名和字段类型

2,生成Dao

有表格了,肯定要有表格的一系列操作增删查改,这就是Dao 的意义

@Dao
public interface BookDao {


    @Insert
    void insertBook(Book book);

    @Delete
    void deleteBook(Book book);

    @Update
    void updateBook(Book book,Auther author);

    @Query("SELECT * FROM book")
    List<Book> queryBook();

    @Query("SELECT * FROM book WHERE bookName = :name")
    List<Book> queryBookByname(String name);

}

加上注解@Dao 即可,其他的没什么区别

3,创建数据库对象

@Database(entities = {Book.class,Auther.class},version = 1)
public abstract class MyRoomDataBase extends RoomDatabase {

    private static final  String DB_name = "roomdb";

    private static  MyRoomDataBase myRoomDataBase;

    public static  synchronized  MyRoomDataBase getInstance(Context context){
        if (myRoomDataBase == null){
            myRoomDataBase = Room.databaseBuilder(context.getApplicationContext(),MyRoomDataBase.class,DB_name).build();

        }
        return  myRoomDataBase;
    }

    public abstract  BookDao bookDao();

    public abstract  AuthorDao authorDao();

}

@Database(entities = {Book.class,Auther.class},version = 1)    数据库中对应表的Entity 类,我这边创建了两种表 Book,Author,

version = 1 对应的是数据版本,升级的时候可以修改

DB_name 修改自己的数据库名称

bookDao 实例化表操作实例

4,app 调用

MyRoomDataBase myRoomDataBase = MyRoomDataBase.getInstance(this);


List<Auther> authers = new ArrayList<>();
authers.add(new Auther("张三",1));
authers.add(new Auther("李四",1));
new Thread(()->{
            myRoomDataBase.runInTransaction(new Runnable() {
                @Override
                public void run() {
                    myRoomDataBase.authorDao().insertAuthor(authers);
                    myRoomDataBase.bookDao().insertBook(new Book("两个人同时写的书"));
                }
            });
        }).start();


 new Thread(()->{
            List<Book> books = myRoomDataBase.bookDao().queryBookByname("两个人同时写的书");

            for (Book book:books){

                Log.e("xss",book.bookName);
            }

        }).start();

我这边因为实例话两张表,所以有两个表操作.这里面需要注意的是调用myRoomDataBase.runInTransaction() 保证同一事务完成操作,即要么都成功,要么都失败.

OK 基本用法就是这样啦

升级数据库

一般是因为表字段有变动 

//修改版本号为2

@Database(entities = {Book.class,Auther.class},version = 2)
public abstract class MyRoomDataBase extends RoomDatabase {

//.....
    public static  synchronized  MyRoomDataBase getInstance(Context context){
        if (myRoomDataBase == null){
            myRoomDataBase = Room.databaseBuilder(context.getApplicationContext(),MyRoomDataBase.class,DB_name).addMigrations(M_1_2).build();

        }
        return  myRoomDataBase;
    }

    
    
    //升级后操作
    static final Migration M_1_2 = new Migration(1,2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            //一般不需要做任何事情
        }
    };

}

升级新增M_1_2,表明版本1 升级到2,如果新增到3,可继续添加

 //升级后操作
    static final Migration M_2_3 = new Migration(2,3) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {


        }
    };
Room.databaseBuilder(context.getApplicationContext(),MyRoomDataBase.class,DB_name).addMigrations(M_1_2,M_2_3).build();

直接修改表

@Entity(tableName = "book")
public class Book {

    //.......省略多余的

    @ColumnInfo(name = "time",typeAffinity = ColumnInfo.TEXT)
    public String time;

    public Book(int id, String bookName,String time) {
        this.id = id;
        this.bookName = bookName;
        this.time = time;
    }
    
    //.....
}

一般都是1升级到2,2升级到3,

如果是1直接升级到3,也需要实现对应的Migration,否则会报错.Migration 空实现就可以了,一般不需要做任何事.

重新运行,用命令行进入应用数据库位置,用下面命令查看,是否生效.

adb shell;

cd /data/data/com.example.testroom/databases;

sqlite3 roomdb;//进入数据库

不知道table 名字的可以

.tables;//参考所有表

sqlite>  pragma table_info ('book');//查看表结构
0|id|INTEGER|1||1
1|bookName|TEXT|0||0
2|time|TEXT|0||0

这样其实也挺麻烦的,ROOM 也提供了可视化的查看方式Schema

在app 的build.gradle 中添加

android {
    //......

    defaultConfig {
        //.....

        javaCompileOptions {
            annotationProcessorOptions {
                arguments += [
                        "room.schemaLocation":"$projectDir/schemas".toString(),
                        "room.incremental":"true"
                ]
            }
        }

    }

$projectDir/schemas

这段的意思是在跟目录下schemas 下记录表格升级的具体详情,每次升级都会记录.

可以看下,我的目录生成了两次升级的信息文件,具体内容我就不加附件了哈,可自行调试.

ps:@Database(entities = {Book.class,Auther.class},exportSchema = true ,version = 2)

exportSchema = true 可以配置是否导出schema 文件,默认是导出的,建议配置导出哈

初始化数据库里面的内容

一些固定数据默认就可以初始化,查看ROOM 迭代过程有新增

Room.databaseBuilder(context.getApplicationContext(),MyRoomDataBase.class,DB_name).createFromAsset("xxxx").addMigrations(M_1_2).build();

Room.databaseBuilder(context.getApplicationContext(),MyRoomDataBase.class,DB_name).

createFromFile(new File("xxxx"))

.createFromAsset("xxxx")

负责加载本地数据,来初始化当前的.

结合ViewModel 使用Room

数据库查询完成还要通知上层更新UI ,这是以前的操作,现在不需要了,可以自动监听数据改变,不要你通知啦

后续更新....

参考

https://developer.android.com/training/data-storage/room?hl=zh-cn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值