【Jetpack】Android Room 資料庫 範例
Android Room 是 Android 開發中的一個持久性庫,用於與 SQLite 數據庫進行交互。它是 Google 官方推薦的一種數據庫解決方案,旨在簡化數據庫操作的開發流程。
Room 提供了一個對象關係映射(Object-Relational Mapping,ORM)的抽象層,允許開發者使用面向對象的方式來訪問和操作數據庫。它將Java對象映射到數據庫表格,並提供了方便的 API 來執行常見的 CRUD 操作(創建、讀取、更新、刪除)。此外,Room還支持數據庫事務、查詢優化和異步操作等功能。
Room 的主要組件包括實體(Entity)、數據訪問對象(Data Access Object,DAO)和數據庫(Database)。開發者需要定義實體類來表示數據庫中的表格,使用 DAO 類定義數據庫操作的方法,並創建數據庫類來定義數據庫的配置和版本管理。
使用 Room 可以大大簡化 Android 應用程序中數據庫操作的編寫工作,提高代碼的可讀性和維護性。它還提供了內建的編譯時檢查和錯誤提示,幫助開發者減少常見的錯誤和提高開發效率。
文章目錄
- Room 導入
- Room 創建 Table
- Room 創建 Dao
- Room 創建 Database
- Room 用法
- Developer Documents Room
1.Room 導入
build.gradle(Module :app)
plugins {
id 'kotlin-kapt'
}
dependencies {
// room
implementation 'androidx.room:room-runtime:2.5.2'
implementation "androidx.room:room-ktx:2.5.2"
kapt 'androidx.room:room-compiler:2.5.2'
// lifecycle
implementation "androidx.fragment:fragment-ktx:1.6.0"
}
2.Room 創建 Table
NotificationEntity.kt
@Entity(tableName = "notification")
data class NotificationEntity(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
val sender: String,
val body: String,
val dateTime: String,
val uuid: String,
val upload: Boolean
)
3.Room 創建 Dao
NotificationDao.kt
@Dao
interface NotificationDao {
@Insert
suspend fun insert(vararg notifications: NotificationEntity)
@Query("DELETE FROM notification")
suspend fun deleteAll()
@Query("SELECT * FROM notification")
fun getNotifications(): Flow<List<NotificationEntity>>
}
4.Room 創建 Database
NotificationDatabase.kt
@Database(entities = [NotificationEntity::class], version = 1)
abstract class NotificationDatabase : RoomDatabase() {
abstract fun notificationDao(): NotificationDAO
companion object {
@Volatile
private var INSTANCE: NotificationDatabase? = null
fun getDatabase(context: Context): NotificationDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context,
NotificationDatabase::class.java,
"NotificationDatabase"
).build()
INSTANCE = instance
instance
}
}
}
}
5.Room 用法
NotificationViewModel.kt
class NotificationViewModel(application: Application) : AndroidViewModel(application) {
private val database = NotificationDatabase.getDatabase(application)
val notifications = database.notificationDao().getNotifications()
fun insert(vararg notifications: NotificationEntity) = viewModelScope.launch {
database.notificationDao().insert(*notifications)
}
fun deleteAll() = viewModelScope.launch {
database.notificationDao().deleteAll()
}
}
class NotificationViewModelFactory(private val application: Application) :
ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(NotificationViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return NotificationViewModel(application) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
NotificationListAdapter.kt
class NotificationListAdapter: ListAdapter<NotificationEntity, RecyclerView.ViewHolder>(DiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return NotificationViewHolder.create(parent)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val notification = getItem(position)
when (holder) {
is NotificationViewHolder -> {
holder.bind(notification.id.toString())
}
}
}
class NotificationViewHolder(private val binding: RecyclerviewItemBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(text: String) {
binding.textView.text = text
}
companion object {
fun create(parent: ViewGroup): NotificationViewHolder {
val binding = RecyclerviewItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return NotificationViewHolder(binding)
}
}
}
class DiffCallback : DiffUtil.ItemCallback<NotificationEntity>() {
override fun areItemsTheSame(oldItem: NotificationEntity, newItem: NotificationEntity): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: NotificationEntity, newItem: NotificationEntity): Boolean {
return oldItem == newItem
}
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val notificationViewModel: NotificationViewModel by viewModels {
NotificationViewModelFactory(application)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
lifecycleScope.launch {
notificationViewModel.deleteAll()
}
binding.add.setOnClickListener {
lifecycleScope.launch {
notificationViewModel.insert(
NotificationEntity(sender = "Father", body = "Hello", dateTime = Instant.ofEpochMilli(System.currentTimeMillis()).toString(), uuid = "AA", upload = false),
NotificationEntity(sender = "Mother", body = "Good Morning", dateTime = Instant.ofEpochMilli(System.currentTimeMillis()).toString(), uuid = "BB", upload = false)
)
withContext(Dispatchers.Main) {
Toast.makeText(this@MainActivity, "Insert success", Toast.LENGTH_SHORT).show()
}
}
}
binding.recyclerview.apply {
val notificationAdapter = NotificationListAdapter()
adapter = notificationAdapter
layoutManager = LinearLayoutManager(this@MainActivity)
setHasFixedSize(true)
lifecycleScope.launch {
notificationViewModel.notifications.collect { notifications ->
notificationAdapter.submitList(notifications)
}
}
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/add"
android:contentDescription="add" />
</androidx.constraintlayout.widget.ConstraintLayout>
recyclerview_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textView"
style="@style/word_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_orange_light" />
</LinearLayout>
6.Developer Documents Room
Open in Documents ViewModel