The use of Room in Android

The Room persistence library provides an abstraction layer on top of SQLite to allow fluent database access while taking full advantage of the power of SQLite. Specifically, Room has the following advantages:

  • Compile-time validation for SQL queries.
  • Handy annotations that minimize repetitive and error-prone boilerplate code.
  • Simplified database migration path.

step1: app/build.gradleIntroduce room in

implementation "androidx.room:room-ktx:2.2.5" 
kapt "androidx.room:room-compiler:2.2.5"

step2: create entity class

This class is the data structure to be stored, by @Entity(tableName="test_table")defining and specifying the table name. Each attribute in the class represents a column in the table . Room will eventually use these properties to create the table and instantiate the object in the database row

//声明数据表,并且指定数据表名称
@Entity(tableName = "test_table")
data class TestEntity(@PrimaryKey(autoGenerate = true) val id: Int, @ColumnInfo(name = "name")val name:String)
//如果列名也叫做word可以省略@ColumnInfo

step3: create DAO

In fact, it is to provide addition, deletion, modification and query to the data table. In DAO (Data Access Objects), you can specify an SQL query and associate it with a method call. @InsertThe compiler examines the SQL and generates queries based on convenient annotations such as . Room uses DAOs to create a clean API for your code. DAO must be an interface or abstract class. By default, all queries must be executed on separate threads. Room supports Kotlin coroutines , you can annotate queries with suspendthe decorator and call them from coroutines or other suspending functions.

@Dao
    interface TestDao {
    
    
    @Query("SELECT * FROM test_table ORDER BY word ASC")
    fun getSavedEntities(): Flow<List<TestEntity>>

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun insert(entity: TestEntity)

    @Query("DELETE FROM test_table")
    suspend fun deleteAll()
}

  • TestDao is an interface, and DAO must be an interface or an abstract class .
  • @DaoThe annotation identifies it as the DAO class of Room.
  • suspend fun insert(word: TestEntity): Declare the pending function to insert a word.
  • @InsertAnnotation is a special kind of DAO method annotation, when using DAO method annotation, you don't need to provide any SQL! (also and annotations for deleting @Deleteand @Update)
  • onConflict = OnConflictStrategy.IGNORE: The selected onConflict strategy ignores new words that are identical to existing words in the list. See the documentation for details on the available conflict strategies .
  • suspend fun deleteAll(): Declare a suspending function to delete all words.
  • There is no annotation to facilitate deletion of multiple entities, so entities should have generic @Queryannotations .
  • @Query("DELETE FROM word_table"): @QueryRequires you to provide a SQL query as a string parameter to the annotation to perform complex read queries and other operations.
  • fun getSavedEntities(): Use Flow to encapsulate the returned List. Flow is an asynchronous sequence of values. Flow generates values ​​one at a time (rather than all values ​​at once) through asynchronous operations such as network requests, database calls, or other asynchronous code. Its API supports coroutines, so coroutines can also be used to complete Flow.
  • @Query("SELECT * test_table ORDER BY word ASC"): A query that returns a list of words sorted in ascending order.

step4: Realize the room database.

Room database class must be abstract and must extend RoomDatabase. Typically only one Room database instance is required for the entire application.

@Database(entities = arrayOf(TestEntity::class), version = 1, exportSchema = false)
        public abstract class TestRoomDatabase : RoomDatabase() {
    
    
    abstract fun wordDao(): TestDao

    companion object {
    
    
        @Volatile
        private var INSTANCE: TestRoomDatabase? = null
        fun getDatabase(context: Context): TestRoomDatabase {
    
    
       
            return INSTANCE ?: synchronized(this) {
    
    
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    TestRoomDatabase::class.java,
                    "test_database"
                ).build()
                INSTANCE = instance
                // return instance
                instance
            }
        }
    }

}

  • Room database classes must be abstract and extend RoomDatabase.
  • You can annotate @Databasethis class as a Room database, and use the annotation parameters to declare the entities in the database and set the version number. Each entity corresponds to a table that will be created in the database. Database migrations are not covered here, so exportSchema has been set to false to avoid build warnings. In a real application, consider setting up a directory for Room to export the schema to check the current schema into the version control system.
  • The database exposes the DAOs through each @Dao's abstract "getter" method.
  • A singleton TestRoomDatabase is defined to prevent multiple instances of the database from being opened at the same time.
  • getDatabase will return the singleton. On first use, it creates the database by using Room's database builder to create a RoomDatabase object in the application context of the TestRoomDatabase class and name it "word_database".

step5: Use DAO in Repository

class TestRepository(private val testDao: TestDao) {
    
    

    val allEntities: Flow<List<TestEntity>> = testDao.getSavedEntities()

   
    @WorkerThread
    suspend fun insert(entity: TestEntity) {
    
    
        testDao.insert(entity)
    }
}

step6: Use Repository in ViewModel

Hilt is used here. First query all the results in the viewModel, convert the flow into liveData, and register the listener in the required activity. When the database data changes, the listener can receive the corresponding change data, such as after calling insert

@HiltViewModel
class TestViewModel @Inject constructor(private val repository: TestRepository) :ViewModel() {
    
    
    val allWords: LiveData<List<Word>> = repository.allEntities.asLiveData()

    fun insert(entity: TestEntity) = viewModelScope.launch {
    
    
        repository.insert(entity)
    }
}

The above is the simple use of Room.

at last

If you want to become an architect or want to break through the 20-30K salary range, then don't be limited to coding and business, but you must be able to select models, expand, and improve programming thinking. In addition, a good career plan is also very important, and the habit of learning is very important, but the most important thing is to be able to persevere. Any plan that cannot be implemented consistently is empty talk.

If you have no direction, here I would like to share with you a set of "Advanced Notes on the Eight Major Modules of Android" written by a senior architect of Ali, to help you organize the messy, scattered and fragmented knowledge systematically and efficiently. Master the various knowledge points of Android development.
insert image description here
Compared with the fragmented content we usually read, the knowledge points of this note are more systematic, easier to understand and remember, and are arranged strictly according to the knowledge system.

Full set of video materials:

1. Interview collection

insert image description here
2. Source code analysis collection
insert image description here

3. The collection of open source frameworks
insert image description here
welcomes everyone to support with one click and three links. If you need the information in the article, directly scan the CSDN official certification WeChat card at the end of the article to get it for free↓↓↓

PS: There is also a ChatGPT robot in the group, which can answer your work or technical questions

Guess you like

Origin blog.csdn.net/weixin_43440181/article/details/131215827