Kotlin实战---使用Room封装本地数据层
没有Kotlin基础的小伙伴先进这里→
Koltin基础文章
Kotlin网络模型的实现→
Kotlin网络模型的实现
kotlin实战---MVP模式实现登录,实现Base层封装→
kotlin实战---MVP模式实现登录,实现Base层封装
1、为什么使用Room
Room 是一个 SQLite 对象映射库。它可用来避免样板代码,还可以轻松地将 SQLite 表数据转换为 Java 对象。Room 提供 SQLite 语句的编译时检查,并且可以返回 RxJava、Flowable 和 LiveData 可观察对象,使用ROOM可以让你更简单,更流畅的操作数据库,使用简单通过注解的方式就能对数据库进行增删改查,Google工程师帮你封装了访问SqlLite的代码,使你的代码性能更高
2、数据库的封装
先来一个图,理清思路再看代码
2.1、LocalRoomRequestManager
接口层实现,类似于网络模块里的API,将操作SqlLite的接口写到这里边
/***
* 数据库获取标准接口,数据库读取
* 只为 LocalRoomRequestManager 服务
* DB 数据
*/
interface IDatabaseRequest {
fun insertStudents(vararg students: Student)
fun updateStudents(vararg students: Student)
fun deleteStudents(vararg students: Student)
fun deleteAllStudent()
fun queryAllStudent() : List<Student> ?
// TODO 可扩展 ...
}
/**
* 为了扩展,这样写(在仓库里面的)
* 本地获取标准接口(在仓库里面) 也就是本地的数据读取(包括本地xml数据,等)
* 只为 LocalRoomRequestManager 服务
*
* xml 数据 本地数据
*/
interface ILocalRequest {
}
复制代码
LocalRoomRequestManager类的实现,初始化的通过dataBase层获取dao,然后通过dao层进行增删改查
class LocalRoomRequestManager :ILocalRequest,IDatabaseRequest{
var studentDao:StudentDao?=null
//相当于Java代码的构造代码块
init{
val studentDatabase=StudentDatabase.getDataBase()
studentDao=studentDatabase?.getStudentDao()
}
companion object{
var INSTANCE: LocalRoomRequestManager? = null
fun getInstance() : LocalRoomRequestManager {
if (INSTANCE == null) {
synchronized(LocalRoomRequestManager::class) {
if (INSTANCE == null) {
INSTANCE = LocalRoomRequestManager()
}
}
}
return INSTANCE!!
}
}
override fun updateStudents(vararg students: Student) {
studentDao?.updateStudents(*students)
}
override fun deleteStudents(vararg students: Student) {
studentDao?.deleteStudent(*students)
}
override fun deleteAllStudent() {
studentDao?.deleteAllStudent()
}
override fun queryAllStudent(): List<Student>? {
return studentDao?.queryAllStudents()
}
override fun insertStudents(vararg students: Student) {
studentDao?.insertStudents(*students)
}
}
复制代码
2.2、Room操作
真正用来操作数据库的代码
初始化数据库
@Database(entities = [Student::class],version = 1)
abstract class StudentDatabase: RoomDatabase() {
abstract fun getStudentDao():StudentDao
companion object{
private var INSTANCE:StudentDatabase?=null
//Application 调用
fun getDatabase(context: Context):StudentDatabase?{
if(INSTANCE==null){
INSTANCE=Room.databaseBuilder(context,StudentDatabase::class.java,"student_database.db")
.allowMainThreadQueries()//允许在主线程查询
.build()
}
return INSTANCE
}
//使用者调用
fun getDataBase():StudentDatabase?= INSTANCE
}
}
复制代码
在Application里去初始化database
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// 初始化
StudentDatabase.getDatabase(this)
}
}
复制代码
Room.databaseBuilde 就是实例化的DataBase的实现类
实现类里的代码:
这些都是框架生成的代码,省去了我们许多的样板代码
Dao层和Entity实现
@Dao
interface StudentDao {
/***
* 可变参数,插入数据
*/
@Insert
fun insertStudents(vararg students:Student)
//更新数据
@Update
fun updateStudents(vararg students:Student)
//根据条件删除
@Delete
fun deleteStudent(vararg students:Student)
//删除全部
@Query("delete from student")
fun deleteAllStudent()
//查询全部
@Query("SELECT * FROM student ORDER BY ID DESC")
fun queryAllStudents():List<Student>
}
@Entity
class Student(){
@PrimaryKey(autoGenerate = true)//设置为主键,自动增长
var id:Int=0
@ColumnInfo(name="name")//别名 数据库中的名字如果不设置,默认是属性名称
lateinit var name:String
@ColumnInfo(name ="phoneNumber")
lateinit var phoneNumber:String
//次构造
constructor(name:String,phoneNumber:String): this(){
this.name=name
this.phoneNumber=phoneNumber
}
}
复制代码
框架生成的代码,大家可以自己去看一下,里面自动添加了事务,也加了锁,非常的nice
写完这些再去用MVP把LocalRoomRequestManager和Model层连起来,MVP上一篇贴的很详细了,这次的就不贴了
Kotlin版的适配器写法
class CollectAdapter :RecyclerView.Adapter<CollectAdapter.MyViewHolder>() {
// 接收 数据库的数据
var allStudents: List<Student> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val layoutInflater: LayoutInflater = LayoutInflater.from(parent.context)
val itemView: View = layoutInflater.inflate(R.layout.item_collect_list, parent, false)
return MyViewHolder(itemView)
}
override fun getItemCount(): Int =allStudents.size
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val student: Student = allStudents[position]
holder.tvID.text = "${position + 1}"
holder.tvName.text = student.name
holder.tvPhoneNumber.text = "${student.phoneNumber}"
}
inner class MyViewHolder(itemView: View):RecyclerView.ViewHolder(itemView){
var tvID: TextView = itemView.findViewById(R.id.tv_id)
var tvName: TextView = itemView.findViewById(R.id.tv_name)
var tvPhoneNumber: TextView = itemView.findViewById(R.id.tv_phoneNumber)
}
}
复制代码
最终的效果
3、总结
需要注意的点在可变参数的传递过程中,不能将参数直接丢给方法得加一个*
LocalRoomRequestManager.getInstance().insertStudents(*students)
体验用Kotlin开发项目的感觉,感觉比Java好用很多,还是很nice的,作为官方直推的语言还是挺值得学习的,
作者:被遗忘的凉白开
链接:https://juejin.cn/post/6955767367192281124
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。