Android—Jetpack教程(四)

这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战

前言

在上一篇中,重点讲解了Jetpack里面的DataBinding组件。在本篇中,将会讲解Jetpack对应的Room组件。

1、Room介绍

那么何为Room?

Android采用SQLLite作为数据库存储,开源社区常见的(ORMObject Relational Mapping)库有ORMLite、GreemDAO等。Room和其他库一样,也是在SQLLite上提供了一层封装

Room重要概念

  • Entity: 实体类,对应的数据库的一张表结构,使用注解@Enity标记
  • Dao: 包含访问一系列访问数据库的方法,使用注解@Dao标记
  • Database 数据库持有者,作为与应用持久化相关数据的底层连接的主要接入点,使用注解@Database标记,另外需要满足以下条件:
    • 定义的类必须是一个继承于RoomDatabase的抽象类
    • 在注解中需要定义与数据库相关联的实体类列表,包含一个没有参数的抽象方法并且返回一个Dao对象

他们之间的关系如下图

1.png

概念说完了,现在开始实战部分!

2、开始实战

2.1 先造对应的Entity

@Entity(tableName = "student")
class Student {

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)
    var id = 0

    @ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT)
    var name: String? = null

    @ColumnInfo(name = "age", typeAffinity = ColumnInfo.INTEGER)
    var age = 0

    constructor(id: Int, name: String?, age: Int) {
        this.id = id
        this.name = name
        this.age = age
    }
    
    @Ignore
    constructor(name: String?, age: Int) {
        this.name = name
        this.age = age
    }

    @Ignore
    constructor(id: Int) {
        this.id = id
    }
}
复制代码

注解解析:

  • @Entity(tableName = "student"),顾名思义,其意表明对应的表名为student

  • @PrimaryKey(autoGenerate = true),表示修饰属性为对应表主键,autoGenerate 为自动增长

  • @ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT),表示为对应的列名,以及对应列名类型

  • @Ignore,表示Room组件将忽略对应构造函数,对应修饰的构造函数只能给开发者用

  • 未使用@Ignore修饰的的构造函数,将由Room组件调用(必须要留一个),当然开发者也可调用。

2.2 接着看对应的Database

满足上面所说:1、继承于RoomDatabase的抽象类;2、返回对应的Dao

@Database(entities = [Student::class], version = 1, exportSchema = false)
abstract class MyDatabase : RoomDatabase() {
    companion object{
        private const val DATABASE_NAME = "my_db.db"
        private var mInstance: MyDatabase? = null
         
        @Synchronized
        @JvmStatic
        open fun getInstance(context: Context): MyDatabase? {
            if (mInstance == null) {
                mInstance = Room.databaseBuilder(
                    context.applicationContext,
                    MyDatabase::class.java,
                    DATABASE_NAME
                ) //.allowMainThreadQueries() 
                    .build()
            }
            return mInstance
        }
    }
    abstract fun getStudentDao(): StudentDao?
}
复制代码

对应@Database(entities = [Student::class], version = 1, exportSchema = false)注解修饰的类,表示为对应的Database

里面内容分别表示为:对应的表名(可多个)、数据库版本、暂时先理解为数据库升级需要使用的标签(后面会详解)

2.3 接下来就是对应的Dao

@Dao
interface StudentDao {

    @Insert
    fun insertStudent(vararg students: Student?)

    @Delete
    fun deleteStudent(vararg students: Student?)

    @Update
    fun updateStudent(vararg students: Student?)

    @Query("SELECT * FROM student")
    fun getAllStudent(): List<Student?>?

    @Query("SELECT * FROM student WHERE id = :id")
    fun getStudentById(id: Int): List<Student?>?
}
复制代码

这里没啥可说的,看对应注解就能知道对应作用。

不过注意的是:这里的WHERE id = :id里面的:id需要和对应方法的形参一一对应。

现在三者都准备好了,来看看如何使用!

2.4 使用Room

class MainActivity : AppCompatActivity(), CoroutineScope by MainScope() {

    private var adapter: StudentRecyclerViewAdapter? = null
    private var studentDao: StudentDao? = null
    private var listStudent: ArrayList<Student> = ArrayList()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val recycleView = findViewById<RecyclerView>(R.id.recycleView)
        recycleView.layoutManager = LinearLayoutManager(this)

        adapter = StudentRecyclerViewAdapter(listStudent)
        recycleView.adapter = adapter

        val database: MyDatabase? = MyDatabase.getInstance(this)
        studentDao = database!!.getStudentDao()
    }

    fun mInsert(view: View?) {
        launch(Dispatchers.Default) {
            val s1 = Student("Jack", 22)
            val s2 = Student("Rose", 18)
            studentDao!!.insertStudent(s1, s2)
        }
    }

    fun mQuery(view: View?) {
        launch(Dispatchers.Default) {
            val students: ArrayList<Student> = studentDao!!.getAllStudent() as ArrayList<Student>
            withContext(Dispatchers.Main) {
                adapter!!.students = students
                adapter!!.notifyDataSetChanged()
            }
        }
    }

    fun mDelete(view: View?) {
        launch(Dispatchers.Default) {
            val s1 = Student(2)
            studentDao!!.deleteStudent(s1)
        }
    }

    fun mUpdate(view: View?) {
        launch(Dispatchers.Default) {
            val s1 = Student(3, "Jason", 21)
            studentDao!!.updateStudent(s1)
        }
    }
}
复制代码

这里为了直观体现Room的作用,暂时使用了比较原始的方式。这样能够快速掌握Room,当掌握Room后再来玩ViewModel+LiveData+DataBinding相关的。

来看看运行效果

在这里插入图片描述 很简单的,不过这里每操作一次都需要额外去查询一次,相当的麻烦。不过在下一篇将会通过LiveData实现自动刷新数据。

Demo:点我下载

Guess you like

Origin juejin.im/post/7034880152995627015