有没有招代理商的网站,定制网站和模板建站哪个更好,网站 方案,邯郸市博物馆一、Room组件概述
Room是Android JetPack架构组件之一#xff0c;是一个持久处理的库。Room提供了在SQLite数据库上提供抽象层#xff0c;使之实现数据访问。 #xff08;1#xff09;实体类#xff08;Entity#xff09;#xff1a;映射并封装了数据库对应的数据表中…一、Room组件概述
Room是Android JetPack架构组件之一是一个持久处理的库。Room提供了在SQLite数据库上提供抽象层使之实现数据访问。 1实体类Entity映射并封装了数据库对应的数据表中对应的结构化数据。实体定义了数据库中的数据表。实体类中的数据域与表的列一一对应。 2数据访问对象Data Access ObjectDAO在DAO中定义了访问数据库的常见的操作例如插入、删除、修改和检索等以达到实现创建映射数据表的实体类对象以及对该实体类对象实例的属性值进行设置和获取的目的。 3数据库Room Database表示对数据库基本信息的描述包括数据库的版本、名称、包含的实体类和提供的DAO对象实例。Room组件中的所有的数据库必须扩展为RoomDatabase抽象类从而实现对实际SQLite数据库的封装。 二、Room组件的配置
在移动应用所在的模块对应的build.gradle中需要进行如下配置:
(1) 增加插件
Groovy DSL
plugins {……id kotlin-kapt
}Kotlin DSL:
plugins{
...id(kotlin-kapt)
}kotlin-kapt实现标注注解处理
(2)增加标注处理的配置
Groovy DSL定义
android {……defaultConfig {……//增加标注处理,增加Schema保存的路径javaCompileOptions{annotationProcessorOptions{//定义标注处理器选项arguments [room.schemaLocation:$projectDir/schemas.toString(),room.incremental:true,room.expandProjection:true]}}
}Kotlin DSL定义
android {……defaultConfig {……//增加标注处理javaCompileOptions{annotationProcessorOptions{//定义标注处理器选项arguments mapOf(room.schemaLocation to $projectDir/schemas.toString(),room.incremental to true,room.expandProjection to true)}}
}(3)增加相关依赖
Groovy DSL定义 def room_version 2.5.0implementationandroidx.room:room-runtime:$room_version// 注释处理工具annotationProcessor androidx.room:room-compiler:$room_version// Kotlin注释处理工具(kapt)kaptandroidx.room:room-compiler:$room_version// kotlin扩展和协同程序对Room的支持implementation androidx.room:room-ktx:$room_version
如果在处理数据库是需要采用rxJava3来实现异步处理这时还需要增加RxJava3库 //增加RxJava库的依赖implementation io.reactivex.rxjava3:rxjava:3.0.7//增加在Android对RxJava库的支持implementation io.reactivex.rxjava3:rxandroid:3.0.0// RxJava3implementation androidx.room:room-rxjava3:$room_versionKotlin DSL定义依赖 val room_version 2.5.0implementation(androidx.room:room-runtime:$room_version)annotationProcessor(androidx.room:room-compiler:$room_version)kapt(androidx.room:room-compiler:$room_version)// kotlin扩展和协同程序对Room的支持implementation(androidx.room:room-ktx:$room_version)// RxJava2implementation(androidx.room:room-rxjava2:$room_version)// RxJava3implementation(androidx.room:room-rxjava3:$room_version)//增加RxJava库的依赖implementation(io.reactivex.rxjava3:rxjava:3.0.7)//增加在Android对RxJava库的支持implementation(io.reactivex.rxjava3:rxandroid:3.0.0)如果在构建模块的过程中出现了java版本不兼容的情况可以调整
android{
...compileOptions {sourceCompatibility JavaVersion.VERSION_17targetCompatibility JavaVersion.VERSION_17}kotlinOptions {jvmTarget 17}
}三、Room组件实现数据库的处理
新建一个项目实现对多位学生的信息写入数据库并执行检索和CRUD操作。
3.1 创建实体类
映射并封装了数据库对应的数据表中对应的结构化数据。实体定义了数据库中的数据表。实体类中的数据域与表的列一一对应。
Entity(tableName students)
data class Student(PrimaryKey(autoGenerate true)ColumnInfo(name studentId) val id:Long,ColumnInfo(name studentNo) val no:String?,ColumnInfo(name studentName) val name:String,ColumnInfo(name studentScore) val score:Int,ColumnInfo(name studentGrade) val grade:String?)
{Ignoreconstructor(no:String,name:String,score:Int,grade:String):this(0,no,name,score,grade)
}定义的实体类Student与数据表students对应。通过标注Entity(tableName “students”)来指定实体类对应的数据表。并对实体类的属性定义通过标注ColumnInfo对应于数据表students中的各个字段并通过PrimaryKey标注来指定数据表的关键字。 注意Room只能识别和使用一个构造器如果存在多个构造器可以使用Ignore让Room忽略这个构造器。因此在上述代码中constructor定义的辅助构造器增加了标注Ignore。 3.2 创建数据访问对象DAO
在数据访问对象DAO是一个接口定义了对指定数据表希望能执行的CRUD操作。
Dao
interface StudentDAO {/*** 插入记录*/Insertfun insertStudent(student:Student):Long/*** 删除记录*/Updatefun updateStudent(student:Student)/*** 删除记录*/Deletefun deleteStudent(student:Student)/*** 检索所有的记录*/Query(select * from students)fun queryAllStudents():ListStudent/*** 检索指定学号的学生记录*/Query(select * from students where studentNo :no)fun queryStudentByNo(no:String):Student}3.3 创建数据库
必须定义一个RoomDatabase的抽象子类来表示对数据库基本信息的描述包括数据库的版本、名称、包含的实体类和提供的DAO对象实例。通过数据库类来达到对实际SQLite数据库的封装。
Database(entities [Student::class], version 1)
abstract class StudentDatabase : RoomDatabase() {abstract fun studentDao(): StudentDAOcompanion object{private var instance: StudentDatabase? null/*** 单例模式创建为一个StudentDatabase对象实例*/Synchronizedfun getInstance(context: Context): StudentDatabase {instance?.let{return it}return Room.databaseBuilder(context,StudentDatabase::class.java,studentDB.db).build()}}
}Database标注表示抽象的类对应数据库内部包括的数据表由标注内部的属性entities指定。如果数据库包括多个数据表entitites可以指定多个实体类的类对象。 在上述的代码中采用了单例模式使得在整个移动应用中只有一个数据库的对象实例在获取这个唯一实例时只有一个线程可以访问因此在getInstance方法中设置标注Synchronized。在这个方法指定创建的数据库名是studentDB.db
3.4 定义并配置应用类
因为在应用中需要获取上下文因此定义应用类并在AndroidManifest进行配置使之易于获取applicationContext上下文对象。
3.4.1定义应用类
class MainApp: Application() {SuppressLint(StaticFieldLeaked)companion object{lateinit var context: Context}override fun onCreate() {super.onCreate()context applicationContext}
}3.4.2 在AndroidManifest.xml配置应用类
在AndroidManifest.xml中需要在application元素中指定已定义的应用类MainApp类似如下代码 ?xml version1.0 encodingutf-8? manifest xmlns:androidhttp://schemas.android.com/apk/res/android
application android:name.MainApp ...
/application
/manifest 3.5 测试数据库的访问
在MainActivity中定义对数据库的测试代码。
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {testDB()}}/*** 测试数据库*/fun testDB() {Observable.createStudent { emitter -//获得Dao对象val dao StudentDatabase.getInstance(MainApp.context).studentDao()//插入记录,测试数据库版本将下列注释取消dao.insertStudent(Student(6001013, 李四, 87, 良好))//检索记录val students dao.queryAllStudents()for (student in students)emitter.onNext(student)}.subscribeOn(Schedulers.io())//指定被观察者的线程处理I/O 操作.observeOn(AndroidSchedulers.mainThread())//指定观察者的线程为主线程.subscribe {Log.d(Ch10_05, ${it})}}
}四、Room组件实现数据库的迁移
移动应用的需求的变化也会导致数据库不断地升级。在数据库升级时会希望保留原有的数据。因此Room提供了数据库迁移的方式来解决数据库的升级。
Room库提供了Migration 类实现数据库增量迁移。每个 Migration 子类提供了Migration.migrate() 函数实现新旧版本数据库之间的迁移路径。当移动应用需要升级数据库时Room 库会利用一个或多个 Migration 子类运行 migrate() 函数在运行时将数据库迁移到最新版本。
在上述的模块的基础上要求修改数据库中数据表students的结构增加一个新的字studentAddress这时需要修改上述代码来完成具体的功能。
4.1 修改实体类
修改实体类Student增加一个属性address并映射数据表students的字段studentAddress,代码如下
Entity(tableName students)
data class Student(PrimaryKey(autoGenerate true)ColumnInfo(namestudentId) val id:Long,ColumnInfo(namestudentNo) val no:String?,ColumnInfo(namestudentName) val name:String,ColumnInfo(namestudentScore) val score:Int,ColumnInfo(name studentGrade) val grade:String?,ColumnInfo(namestudentAddress) val address:String?){Ignoreconstructor(no:String,name:String,score:Int,grade:String,address:String):this(0,no,name,score,grade,address)
}4.2 修改数据库
因为数据表变化这时需要修改数据库变更数据库的版本为2。定义Migration对象指定数据库迁移是从版本1迁移到版本2并覆盖migrate的方法执行具体迁移的操作。
Database(entities [Student::class], version 2)
abstract class StudentDatabase : RoomDatabase() {abstract fun studentDao(): StudentDAOcompanion object{private var instance: StudentDatabase? null//数据库从版本1迁移到版本2val MIGRATION_1_2 object : Migration(1, 2) {//迁移方法定义override fun migrate(database: SupportSQLiteDatabase) {//修改数据表students增加一个新的字段address数据类型为TEXT字符串database.execSQL(ALTER TABLE students ADD COLUMN studentAddress TEXT)}}/*** 单例模式创建为一个StudentDatabase对象实例*/Synchronizedfun getInstance(context:Context):StudentDatabase{instance?.let{return it}return Room.databaseBuilder(context,StudentDatabase::class.java,studentDB.db).addMigrations(MIGRATION_1_2).build().apply{instance this}}}
}在上述代码的getInstance返回数据库对象时通过调用addMigrations进行处理迁移的操作。
4.3 修改测试代码
在上述修改的前提基础上因数据库的变更测试代码也进行修改代码如下
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {testDB()}}/*** 数据库版本2的测试函数*/fun testDB(){Observable.createStudent{ emitter -//获得Dao对象val dao StudentDatabase.getInstance(MainApp.context).studentDao()//插入记录dao.insertStudent(Student(6001015,王五,87,良好,江西省南昌红谷大道999号))//检索记录val students dao.queryAllStudents()for(student in students)emitter.onNext(student)}.subscribeOn(Schedulers.io())//指定被观察者的线程处理I/O 操作.observeOn(AndroidSchedulers.mainThread())//指定观察者的线程为主线程.subscribe{ it: Student -Log.d(TAG,${it})}}
}参考文献
陈轶《Android移动应用开发微课版》[M] 北京清华大学出版社 2022 P407-P419