雖然是jetpack的套件之一 但不一定會放到之前寫了好幾天的MVVM專案內
篇幅預計是三篇 兩篇實作一篇寫tests要看有沒有時間 快難產了
這三篇的solution會放在最下面 可以直接去下載 或是跟著這幾篇一路撰寫下去
本篇會參考
https://codelabs.developers.google.com/codelabs/android-room-with-a-view-kotlin/index.html?index=..%2F..index#0
撰寫一個簡單的專案使用room的基本功能
簡介:
Room是SQLite的抽象層,能讓你更簡單使用SQLite的功能,而且如果有SQL語法錯誤能在編譯階段就報錯,減少除錯時間。
ROOM簡單分成三個部分
Database - 資料來源實體
Entity - 數據庫的表單
DAO (database access object) - 提供訪問數據庫的方法 通常會在DAO上面再加一層Repository避免直接使用DAO
簡介完了 那麼開始撰寫專案
首先先開啟新的專案
選擇base Activity
專案名稱任意
記得勾選 Use AndroidX artifacts
前置作業
build.gradle (Module: app)
dependencies{
implementation "androidx.room:room-runtime:$rootProject.roomVersion"
annotationProcessor "androidx.room:room-compiler:$rootProject.roomVersion"
androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"
// Lifecycle components
implementation "androidx.lifecycle:lifecycle-extensions:$rootProject.archLifecycleVersion"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$rootProject.archLifecycleVersion"
// Testig
androidTestImplementation "androidx.arch.core:core-testing:$rootProject.coreTestingVersion"
}
接著在專案名稱的build檔案新增以下片段
build.gradle(Project:YourProjectName)
ext {
roomVersion = '2.1.0-rc01'
archLifecycleVersion = '2.1.0-rc01'
androidxArchVersion = '2.1.0-rc01'
coroutines = '1.3.0'
}
然後可以開始撰寫專案了
先新增物件實體
WordEntity.kt
@Entity(tableName = "word_table")
data class WordEntity(
@PrimaryKey
@ColumnInfo(name = "word")
val word: String
)
再新增
DAO
//DAO類需為 interface or abstract
WordDao.kt
@Dao
interface WordDao {
// Query 填寫sql語法
// ORDER BY Column_name 排序結果 ASC 代表由小往大 DESC 大到小
@Query("SELECT * FROM word_table ORDER BY word ASC")
fun getAllWords():LiveData<WordEntity>
//Insert有保留語法
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(wordEntity: WordEntity)
@Query("DELETE FROM word_table")
suspend fun deleteAll()
}
接著新增Repository 透過Repository來存取資料而不是直接使用DAO
//DAO包含所有的讀/寫與其他方法 透過Repository訪問DAO取用需要的fun就好
WordRepository.kt
class WordRepository(private val wordDao: WordDao) {
val allWords: LiveData<List<WordEntity>> = wordDao.getAllWords()
suspend fun insert(word: WordEntity) {
wordDao.insert(word)
}
}
新建單例Database
//database class 需使用抽象類並且繼承RoomDatabase
WordRoomDatabase.kt
@Database(entities = arrayOf(WordEntity::class), version = 1)
public abstract class WordRoomDatabase : RoomDatabase() {
abstract fun WordDao(): WordDao
companion object {
//Volatile 用來避免編譯器優化
@Volatile
private var INSTANCE: WordRoomDatabase? = null
fun getDatabase(context: Context): WordRoomDatabase {
val tempInstance = INSTANCE
if (tempInstance != null) {
return tempInstance
} else {
synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
WordRoomDatabase::class.java,
"word_database"
).build()
INSTANCE = instance
return instance
}
}
}
}
}
接著創建viewModel管理與分派資料
WordViewModel.kt
class WordViewModel(application: Application) : AndroidViewModel(application) {
private val repository: WordRepository
val allWords: LiveData<List<WordEntity>>
init {
//從WordRoomDatabase引用唯一的wordDao構築WordRepository
val wordDao = WordRoomDatabase.getDatabase(application).WordDao()
repository = WordRepository(wordDao)
allWords = repository.allWords
}
fun insertWord(word:WordEntity)= viewModelScope.launch {
repository.insert(word)
}
}
到此room的前置作業就完成了
明天開始建置簡單的畫面來呈現資料
solution
https://github.com/mars1120/jetpackMvvmDemo/tree/room