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
@Enity
tag - The Dao:Contains access to a list of methods to access the database, using annotations
@Dao
tag - DatabaseThe database holder, as the primary access point for the underlying connection to application persistence-related data, uses annotations
@Database
In 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