This is the 25th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

preface

In the previous article, I focused on the DataBinding component in Jetpack. In this article, we’ll look at the Room component for Jetpack.

1. Room introduction

So what is Room?

Android uses SQLLite as database storage, and common ORMObject Relational Mapping libraries in the open source community include ORMLite, GreemDAO, etc. Room, like the other libraries, provides a layer of encapsulation on SQLLite.

Important Concepts of Room

  • The Entity:Entity class, a table structure corresponding to the database, uses annotations@Enitytag
  • The Dao:Contains access to a list of methods to access the database, using annotations@Daotag
  • DatabaseThe database holder, as the primary access point for the underlying connection to application persistence-related data, uses annotations@DatabaseIn addition, the following conditions must be met:
    • The class defined must be an abstract class that inherits from RoomDatabase
    • In the annotations you need to define a list of entity classes associated with the database, containing an abstract method with no parameters and returning a Dao object

Their relationship is shown below

That’s the concept, now for the real part!

2. Get started

2.1 Create the Entity first

@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
    }
}
Copy the code

Note:

  • @entity (tableName = “student”), which, as the name implies, indicates that the corresponding table is named student

  • @primarykey (autoGenerate = true) : indicates that the modified property is the PrimaryKey of the corresponding table, and autoGenerate indicates automatic growth

  • @columninfo (name = “name”, typeAffinity = columninfo.text), which represents the corresponding column name and the corresponding column name type

  • @ignore, which indicates that the Room component will Ignore the corresponding constructor, and that the corresponding modified constructor is available only to developers

  • Constructors that are not decorated with @ignore are called by the Room component (one must be left behind) and can be called by the developer.

2.2 Go to the corresponding Database

1. Abstract classes inherited from RoomDatabase; 2. Return the corresponding 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(a): StudentDao?
}
Copy the code

Class that corresponds to @database (entities = [Student::class], version = 1, exportSchema = false)

The contents are respectively represented as: the corresponding table name (multiple), database version, temporarily understood as the label used for database upgrade (will be explained in detail later)

2.3 Next comes the 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(a): List<Student? >?@Query("SELECT * FROM student WHERE id = :id")
    fun getStudentById(id: Int): List<Student? >? }Copy the code

There’s nothing to say here, but look at the corresponding annotations to see what the corresponding functions are.

WHERE id = :id WHERE id = :id WHERE id = :id

Now that all three are ready, let’s see how to use them!

2.4 use the 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) {
            valstudents: ArrayList<Student> = studentDao!! .getAllStudent()asArrayList<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) } } }Copy the code

Here, in order to intuitively reflect the role of Room, a relatively primitive way is temporarily used. This allows you to quickly master Room, and when you master Room, you can play ViewModel+LiveData+DataBinding.

Let’s see how it works

Very simple, but here every operation need to go to an additional query, quite troublesome. In the next article, however, we will implement automatic data refresh through LiveData.

The Demo:Let me download