当前位置: 首页 > news >正文

黑龙江网站建设鞍山网站制作

黑龙江网站建设,鞍山网站制作,北京经济技术开发区建设局网站,个人注什么域名的网站文章目录 一、Room简介二、用RoomViewModelLiveData增删改查数据三、下载源码 一、Room简介 Room是Google推出的数据库框架,是一个 ORM (Object Relational Mapping)对象关系映射数据库、其底层还是对SQLite的封装。 Room包含三个主要组件: 数据库类&…

文章目录

  • 一、Room简介
  • 二、用Room+ViewModel+LiveData增删改查数据
  • 三、下载源码

一、Room简介

RoomGoogle推出的数据库框架,是一个 ORM (Object Relational Mapping)对象关系映射数据库、其底层还是对SQLite的封装。

Room包含三个主要组件:

  • 数据库类(DataBase),用于保存数据库并作为应用持久性数据底层连接的主要访问点。
  • 数据实体(Entity),用于表示应用的数据库中的表。
  • 数据访问对象 (DAO),提供您的应用可用于查询、更新、插入和删除数据库中的数据的方法。
  • @Entity 表结构实体
  • @PrimaryKey 主键
  • @ColumnInfo 列/字段信息

二、用Room+ViewModel+LiveData增删改查数据

EntityDaoDatabase 操作数据库
数据库的每个表,都对应一个Entity,一个DaoDao负责增删改查操作)

项目RoomDemo,如下图:

build.gradle添加如下依赖:

plugins {id 'com.android.application'id 'kotlin-android'id 'kotlin-android-extensions'id 'kotlin-kapt'
}dependencies {def room_version = "2.3.0"implementation "androidx.room:room-runtime:$room_version"annotationProcessor "androidx.room:room-compiler:$room_version"kapt "androidx.room:room-compiler:$room_version"
}

首先,创建一个数据表Student。先创建包名,在com.bignerdranch.roomdemo下创建一个db包,db下创建bean包,bean包下创建Student类。

package com.bignerdranch.roomdemo.db.beanimport androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import org.jetbrains.annotations.NotNull@Entity(tableName = "student")
class Student {@NotNull@PrimaryKey(autoGenerate = true)@ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)var id = 0@NotNull@ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT)var name: String@NotNull@ColumnInfo(name = "age", typeAffinity = ColumnInfo.TEXT)var age: String/*** Room会使用这个构造器来存储数据,也就是当你从表中得到Student对象时候,Room会使用这个构造器*/constructor(id: Int, name: String, age: String) {this.id = idthis.name = namethis.age = age}/*** 由于Room只能识别和使用一个构造器,如果希望定义多个构造器,你可以使用Ignore标签,让Room忽略这个构造器* 同样,@Ignore标签还可用于字段,使用@Ignore标签标记过的字段,Room不会持久化该字段的数据*/@Ignoreconstructor(name: String, age: String) {this.name = namethis.age = age}
}

这个@Entity就是表示数据库中的表,Student类对应就是Student表,@PrimaryKey表示主键,这里是idautoGenerate = true 是自增,@NonNull表示不为空。 @ColumnInfo表示表中的列名,name = "name"表示列名的值。

下面在db包下新建一个dao包,创建StudentDao,里面的代码如下:

package com.bignerdranch.roomdemo.db.daoimport androidx.lifecycle.LiveData
import androidx.room.*
import com.bignerdranch.roomdemo.db.bean.Student@Dao
interface StudentDao {@Insertfun insertStudent(student: Student?)@Deletefun deleteStudent(student: Student?)@Updatefun updateStudent(student: Student?)@Query("SELECT * FROM student")fun getStudentList(): LiveData<List<Student?>?>? //希望监听学生表的变化,为其加上LiveData@Query("SELECT * FROM student WHERE id = :id")fun getStudentById(id: Int): Student?
}

StudentDao是一个接口,主要是定义了一些方法,通过注解在编译的时候会生成实现类。
然后,新建main/assets/databases,并在其中放置student.db文件,其位置如下:

SQLite软件导入students.db文件,如下图:

然后,在MyDatabase.kt中,用createFromAsset()方法从assets/database/students.db创建Room数据库,下面是数据库的创建,在db包下新建一个MyDatabase类,继承RoomDatabase,代码如下:

package com.bignerdranch.roomdemo.dbimport android.content.Context
import android.util.Log
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.bignerdranch.roomdemo.db.bean.Student
import com.bignerdranch.roomdemo.db.dao.StudentDao@Database(entities = [Student::class], exportSchema = false, version = 1)
abstract class MyDatabase() : RoomDatabase() {abstract fun studentDao(): StudentDao?companion object {private val DATABASE_NAME = "my_db"private var databaseInstance: MyDatabase? = null@Synchronized //已同步fun getInstance(context: Context): MyDatabase? {if (databaseInstance == null) {databaseInstance = Room.databaseBuilder(context.applicationContext,MyDatabase::class.java,DATABASE_NAME).createFromAsset("databases/student.db").fallbackToDestructiveMigration()
//                    .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_1_3, MIGRATION_3_4).build()}return databaseInstance}val MIGRATION_1_2: Migration = object : Migration(1, 2) {override fun migrate(database: SupportSQLiteDatabase) {//do somethingLog.d("MyDatabase", "MIGRATION_1_2")}}private val MIGRATION_2_3: Migration = object : Migration(2, 3) {override fun migrate(database: SupportSQLiteDatabase) {//do somethingLog.d("MyDatabase", "MIGRATION_2_3")}}private val MIGRATION_1_3: Migration = object : Migration(1, 3) {override fun migrate(database: SupportSQLiteDatabase) {//do somethingLog.d("MyDatabase", "MIGRATION_1_3")}}val MIGRATION_3_4: Migration = object : Migration(3, 4) {override fun migrate(database: SupportSQLiteDatabase) {Log.d("MyDatabase", "MIGRATION_3_4")database.execSQL("CREATE TABLE temp_Student (" +"id INTEGER PRIMARY KEY NOT NULL," +"name TEXT," +"age TEXT)")database.execSQL("INSERT INTO temp_Student (id, name, age) " +"SELECT id, name, age FROM Student")database.execSQL("DROP TABLE Student")database.execSQL("ALTER TABLE temp_Student RENAME TO Student")}}}
}

这里的@Database注解表示这个类是用来操作数据库的,entities = [Student::class]表示当前数据库中的表,只有一个Student表,多的表用应用逗号隔开。version = 1表示数据库的版本,可以做数据库的升级操作。createFromAsset()Room库中提供的。

注意这是一个抽象类,在编译时Room会帮助构建实现类。

现在运行一下,手机或者模拟器都可以。然后什么都不用去做。

可以查看到,MyDatabaseStudentDao的实现类都自动生成了。

ViewModel内:通过 Room.Database查到LiveData数据,在外部监听LiveData
Room变化时,通过ViewModel内的LiveData通知页面数据的变化,架构如下:

新建StudentViewModel类,该类继承自AndroidViewModel,其中有DatabaseLiveData,代码如下:

package com.bignerdranch.roomdemo.jetpackroomwithlivedataandviewmodeltestimport android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import com.bignerdranch.roomdemo.db.MyDatabase
import com.bignerdranch.roomdemo.db.bean.Studentclass StudentViewModel(application: Application) : AndroidViewModel(application) {private val myDatabase: MyDatabase?val liveDataStudent: LiveData<List<Student?>?>?init {myDatabase = MyDatabase.getInstance(application)liveDataStudent = myDatabase!!.studentDao()!!.getStudentList()}}

表操作无非就是那么几个,增删改查,但是为了更直观的显示结果,需要对UI做一些改动。

在工程的build.gradle中增加repositories闭包中增加jitpack库。

然后在appbuild.gradle中的dependencies{}比包中增加

implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6'

1. 修改布局
Sync一下,下面修改一下页面的布局文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/btnInsertStudent"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_margin="12dp"android:text="Add a Student"android:textAllCaps="false" /><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="wrap_content" />
</LinearLayout>

在这里插入图片描述

这里就是一个按钮和一个列表,下面创建列表的item布局
layout下新建一个list_item_student.xml布局,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:paddingTop="12dp"android:paddingBottom="12dp"><TextViewandroid:id="@+id/tvId"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center" /><TextViewandroid:id="@+id/tvName"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center" /><TextViewandroid:id="@+id/tvAge"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:gravity="center" /></LinearLayout>

在这里插入图片描述

新建dialog_layout_student.xml,布局如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><EditTextandroid:id="@+id/etName"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:autofillHints=""android:hint="Name" /><EditTextandroid:id="@+id/etAge"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:autofillHints=""android:hint="Age" /></LinearLayout>

在这里插入图片描述

com.bignerdranch.roomdemo下新建一个adapter包,包下新建StudentAdapter类,作为列表数据的适配器。代码如下:
2. 列表适配器

package com.bignerdranch.roomdemo.adapterimport com.bignerdranch.roomdemo.R
import com.bignerdranch.roomdemo.db.bean.Student
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import kotlinx.android.synthetic.main.list_item_student.view.*class StudentAdapter(layoutResId: Int = R.layout.list_item_student) :BaseQuickAdapter<Student, BaseViewHolder>(layoutResId) {override fun convert(holder: BaseViewHolder, item: Student) {holder.itemView.run {tvId.text = item.id.toString()tvName.text = item.nametvAge.text = item.age}}
}

然后,在MainActivity中初始化List,实例化StudentViewModel并监听其LiveData的变化,代码如下:

package com.bignerdranch.roomdemoimport android.content.DialogInterface
import android.os.AsyncTask
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.bignerdranch.roomdemo.adapter.StudentAdapter
import com.bignerdranch.roomdemo.db.MyDatabase
import com.bignerdranch.roomdemo.db.bean.Student
import com.bignerdranch.roomdemo.jetpackroomwithlivedataandviewmodeltest.StudentViewModel
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.listener.OnItemLongClickListener
import kotlinx.android.synthetic.main.activity_main.recyclerView/**** @date*/
class MainActivity : AppCompatActivity(), OnItemLongClickListener {private val mStudentAdapter by lazy {StudentAdapter().apply {setOnItemLongClickListener(this@MainActivity)}}private var myDatabase: MyDatabase? = nullprivate var studentList: MutableList<Student>? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)findViewById<View>(R.id.btnInsertStudent).setOnClickListener {openAddStudentDialog()}studentList = ArrayList()val layoutManager = LinearLayoutManager(this@MainActivity)layoutManager.orientation = LinearLayoutManager.VERTICALrecyclerView.layoutManager = layoutManagerrecyclerView.adapter = mStudentAdapter
//        mStudentAdapter.setList(studentList)myDatabase = MyDatabase.getInstance(this)val studentViewModel: StudentViewModel =ViewModelProvider(this)[StudentViewModel::class.java]studentViewModel.liveDataStudent!!.observe(this) { students ->(studentList as ArrayList<Student?>).clear()(studentList as ArrayList<Student?>).addAll(students!!)
//            studentAdapter2!!.notifyDataSetChanged()mStudentAdapter.setList(studentList)mStudentAdapter.notifyDataSetChanged()}}private fun updateOrDeleteDialog(student: Student?) {val options = arrayOf("更新", "删除")AlertDialog.Builder(this@MainActivity).setTitle("").setItems(options) { _, which ->if (which == 0) {openUpdateStudentDialog(student)} else if (which == 1) {if (student != null) {DeleteStudentTask(student).execute()}}}.show()}private fun openAddStudentDialog() {val customView: View = this.layoutInflater.inflate(R.layout.dialog_layout_student, null)val etName = customView.findViewById<EditText>(R.id.etName)val etAge = customView.findViewById<EditText>(R.id.etAge)val builder = AlertDialog.Builder(this@MainActivity)val dialog = builder.create()dialog.setTitle("Add Student")dialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK") { dialog, which ->if (TextUtils.isEmpty(etName.text.toString()) || TextUtils.isEmpty(etAge.text.toString())) {Toast.makeText(this@MainActivity, "输入不能为空", Toast.LENGTH_SHORT).show()} else {InsertStudentTask(etName.text.toString(), etAge.text.toString()).execute()}}dialog.setButton(DialogInterface.BUTTON_NEGATIVE,"CANCEL") { dialog, which -> dialog.dismiss() }dialog.setView(customView)dialog.show()}private fun openUpdateStudentDialog(student: Student?) {if (student == null) {return}val customView: View = this.layoutInflater.inflate(R.layout.dialog_layout_student, null)val etName = customView.findViewById<EditText>(R.id.etName)val etAge = customView.findViewById<EditText>(R.id.etAge)etName.setText(student.name)etAge.setText(student.age)val builder = AlertDialog.Builder(this@MainActivity)val dialog = builder.create()dialog.setTitle("Update Student")dialog.setButton(DialogInterface.BUTTON_POSITIVE, "OK") { dialog, which ->if (TextUtils.isEmpty(etName.text.toString()) || TextUtils.isEmpty(etAge.text.toString())) {Toast.makeText(this@MainActivity, "输入不能为空", Toast.LENGTH_SHORT).show()} else {UpdateStudentTask(student.id,etName.text.toString(),etAge.text.toString()).execute()}}dialog.setButton(DialogInterface.BUTTON_NEGATIVE,"CANCEL") { dialog, which -> dialog.dismiss() }dialog.setView(customView)dialog.show()}private inner class InsertStudentTask(var name: String, var age: String) :AsyncTask<Void?, Void?, Void?>() {override fun doInBackground(vararg params: Void?): Void? {myDatabase!!.studentDao()!!.insertStudent(Student(name, age))return null}}private inner class UpdateStudentTask(var id: Int, var name: String, var age: String) :AsyncTask<Void?, Void?, Void?>() {override fun doInBackground(vararg params: Void?): Void? {myDatabase!!.studentDao()!!.updateStudent(Student(id, name, age))return null}}private inner class DeleteStudentTask(var student: Student) : AsyncTask<Void?, Void?, Void?>() {override fun doInBackground(vararg params: Void?): Void? {myDatabase!!.studentDao()!!.deleteStudent(student)return null}}override fun onItemLongClick(adapter: BaseQuickAdapter<*, *>,view: View,position: Int): Boolean {updateOrDeleteDialog((studentList as ArrayList<Student?>)[position])return true}
}

运行后,当LiveData数据变化时,更新UI即可,而不需要每次增删改后都必须用QueryStudentTask() 来手动查询一次数据库,简化了系统,效果如下:

三、下载源码

下载源码github地址:https://github.com/caobin10/RoomDemo

http://www.yayakq.cn/news/724092/

相关文章:

  • 科技网站推荐成都智能建站模板
  • 网站后台开发做什么建设网站前的市场分析主要包括哪些内容
  • 长沙住房和建设局网站湖南省郴州市北湖区邮政编码
  • 星大建设集团招聘网站地方信息网站怎么做
  • 公司招聘网站 哪个部门做logo查询有没有注册过
  • 成都网站设公司门户网站开源
  • 关于网站建设的合同范本正规视频网站建设 方案
  • 网站设计要素 优帮云wordpress+悬浮按钮
  • Dw制作个人网站智汇团建网站登录平台
  • 个人开发网站分销系统app
  • 商城网站建设 数商云短视频seo获客
  • 深圳网站建设网络推广seo怎么做优化工作
  • 软件网站设计移动互联网开发技术期末试题
  • 网站建设作品图片网页设计表单注册代码
  • wordpress 双语网站你注册过哪些网站
  • 如何做一个大型网站账号权重查询入口站长工具
  • 做网站有高手没有精品网站模板
  • 网站设计教程及在线模拟器住房和城乡建设部网站造价师
  • 哪里公司建设网站好桑福生物科技网站开发
  • 医药类网站怎么做seo安徽网站建设公司哪家好
  • 上海高端网站开发本科自考报名
  • 网站关联页面如何做网站模板 代码免费
  • 浏阳商务局网站溪江农贸市场建设网站排名优化软件联系方式
  • 普陀建设机械网站安阳市城乡建设规划局网站
  • 做旅游网站有前途吗凡科如何开通网站建设
  • 沙河高端网站建设上海景泰建设有限公司网站
  • 网站建设怎么搞公众号怎么挣钱
  • 100款不良网站进入窗口软件制作网页计算器
  • 网站开发的概念中国机械加工信息网
  • 什么是网站建设和维护建筑设计方案大全