四、使用Jetpack Compsoe编写一个写小说的Android应用:Room数据库的建立

前排叠甲:同上一篇

走到这一步之后,我们不再新增简单的页面和跳转,从开始我们就忽视了数据的问题,从这里开始将给软件添加一个本地数据库。毕竟写小说的软件说实话并不适合建立网上数据库,这样成本比较高,有泄露风险。做一个本地数据库的话则可以很好的解决这些问题。

当然,本地数据库则无法在其他端查看,软件卸载时会随着软件清除其中数据,因此以后的数据导入和导出也很重要!

1、Room数据库的引入

说实话我并不知道哪个数据库更方便快捷,只是这个Room数据库用起来比较方便,所以就用它了。

首先在gradle(Module:app)中引入依赖:

dependencies {
    implementation("androidx.room:room-runtime:2.5.1")
    ksp("androidx.room:room-compiler:2.5.1")
    implementation("androidx.room:room-ktx:2.5.1")
}

这时候,ksp应该会报错,

因为编译器本身并未添加ksp插件,因此需要进行一系列操作:

1.1、在gradle(Module:app)中开头位置引入id

plugins {
    id("com.google.devtools.ksp")
}

1.2、修改编译版本

将原来的1.8改为17,如下:

修改前:

修改后:

1.3在gradle(Project)中添加插件【注意是另外一个文件】

plugins {
    id("com.google.devtools.ksp") version "1.8.10-1.0.9" apply false
}

1.4在settings文件中添加国内镜像网址(为了防止以后有些包下载速度太慢,不加应该也行,反正我加了)

原来:

添加后:

代码如下:

maven { url = uri( "https://maven.aliyun.com/repository/public") }
maven { url = uri( "https://maven.aliyun.com/repository/google" )}
maven { url = uri( "https://maven.aliyun.com/repository/gradle-plugin") }
google()
mavenCentral()
gradlePluginPortal()
maven { url = uri( "https://maven.google.com") }

以上步骤完成后点击同步,完成Room数据库依赖包的安装。

2、新建数据类Entities

首先新建database的文件夹

之后新建Entities文件,用来存放不同的数据类:

@Entity(tableName = "fictionData")
data class Book(

    @PrimaryKey(autoGenerate = true)
    val numberId: Int = 0,

    @ColumnInfo(name = "fiction_id")
    var fictionId: Int = 0,

    @ColumnInfo(name = "fiction_name")
    var fictionName: String? = null,

    )

@Entity(tableName = "chapterData")
data class Chapter(

    @PrimaryKey(autoGenerate = true)
    val selfId: Int = 0,

    @ColumnInfo(name = "fiction_id")
    var fictionId: Int = 0,

    @ColumnInfo(name = "chapter_id")
    var chapterId: Int = 0,

    @ColumnInfo(name = "chapter_Name")
    var chapterName: String? = "null",

    @ColumnInfo(name = "chapter_text")
    var chapterText: String? = "null",

    @ColumnInfo(name = "last_update_time")
    var lastUpdateTime: String = ""

)

@Entity(tableName = "dictionaryData")
data class Dictionary(

    @PrimaryKey(autoGenerate = true)
    val selfId: Int = 0,

    @ColumnInfo(name = "fiction_id")
    var fictionId: Int = 0,

    @ColumnInfo(name = "chapter_id")
    var chapterId: Int = 0,

    @ColumnInfo(name = "dic_item_id")
    var dicItemId: Int = 0,

    @ColumnInfo(name = "dic_item_type")
    var dictItemType: Int = 0,

    @ColumnInfo(name = "dic_item_name")
    var dictItemName: String = "",

    @ColumnInfo(name = "dic_item_detail")
    var dictItemDetail: String = ""

)

从上面代码中可以看到,我新建了三个数据类,实际根据你的需求来,而且第三个dictionaryData是之前的,之后可能会改,暂时先放在这,反正目前也没用到。

怎么使用相信你看看上面的代码就能了解个大概了,PrimaryKey是必须要有的,这是SQL数据表的基础知识这里就不说了,其他的话就是写一个ColumnInfo,数据表多一列,没啥难的地方。

3、创建数据库操作接口Dao

在database文件夹内新建一个CreateBookDao的接口文件,注意在创建时选择interface类型

之后写入数据库操作函数

@Dao
interface CreateBookDao {

    @Insert
    suspend fun insertBook(book: Book)

    @Update
    suspend fun updateBook(book: Book)

    @Insert
    suspend fun insertChapter(chapter: Chapter)

    //获取id最大的书
    @Query("SELECT * FROM fictionData ORDER BY fiction_id DESC LIMIT 1")
    suspend fun getLastBookId(): Book?

    //获取一本书的id号,用于后续删除
    @Query("SELECT * FROM fictionData WHERE fiction_id = :idF")
    suspend fun getBookOfId(idF: Int): Book?
    
}

可以看到操作函数包含了增删改查的基本内容,只是示例这些函数怎么写,后续会不会用到就再说了。

4、创建数据库

在上述两步创建完成后,就可以创建本软件的数据库了,在database文件夹中新建AppDatabase文件,并写入如下代码:

@Database(
    entities = [Book::class, Chapter::class, Dictionary::class],
    version = 1,
    exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {
    abstract fun createBookDao(): CreateBookDao

    companion object {
        @Volatile
        private var instance: AppDatabase? = null

        fun getInstance(context: Context): AppDatabase {
            return instance ?: synchronized(this) {
                Room.databaseBuilder(
                    context,
                    AppDatabase::class.java,
                    "fiction_database"
                )
                    .build().also { instance = it }
            }
        }
    }
}

这段代码中,函数名上边的Database括号里面的,一个是刚刚写的数据类,一个是数据库版本,最后一个好像是导出什么数据库操作之类的,false就对了。

其次,定义好的接口要用的时候都是这么声明。

abstract fun createBookDao(): CreateBookDao

然后下面的数据库这段代码直接复制就行,我也不知道,但是这样写是最好的,你看到的其他简化方法都会影响数据库的稳定性,这里面能改的只有getInstance的这个函数名。

好的到这里数据库整套就创建完成了,当然它不能运行,因为数据库只能在后台线程运行,如果你在主线程运行的话,当你操作大量数据时,会导致UI无响应,主线程只负责UI的刷新,所以其他操作都要移动到子线程去。

之后我们要做的是实现Room的功能,那么这里就要用到另外一个东西:ViewModel。

说实话,这个东西我也没搞明白,所幸根据官方给的例子跑通了整个代码,但是你让我解释其中为什么要这么做,我应该是解释不了,毕竟我只想实现我的软件功能,并不想系统的把所有知识掌握。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HO灵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值