Android Room數(shù)據(jù)庫的基本使用示例詳解
一、什么是Room
1.1 Room簡介
Room是Android Jetpack組件庫中的一部分,對SQLite進(jìn)行了封裝,簡化了對SQLite數(shù)據(jù)庫的操作,讓開發(fā)者使用面向?qū)ο蟮姆绞剑ㄍㄟ^Java/Kotlin)來操作SQLite數(shù)據(jù)庫,從而避免了編寫大量繁瑣的SQL代碼和解析數(shù)據(jù)。
1.2 三大核心組件
- Entity(實體類):用于表示數(shù)據(jù)庫表的數(shù)據(jù)結(jié)構(gòu)。
- DAO(Data Access Object):用于定義數(shù)據(jù)庫操作的方法。
- Database(數(shù)據(jù)庫類):用于創(chuàng)建數(shù)據(jù)庫實例,并將 Entity 和 DAO 關(guān)聯(lián)起來
二、集成Room
在app下的build.gradle下添加:
//數(shù)據(jù)庫創(chuàng)建成功,會有類似以下目錄,以自己的為準(zhǔn)\build\generated\source\kapt\release\com\xxx\xxx\drive\database\AppDatabase_Impl
def room_version = "2.5.1"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-ktx:$room_version"
//這里注意:如果是某一個moudle中要使用room數(shù)據(jù)庫,建議直接將庫集成到moudle中的build.gradle中,博主這里遇到將root相關(guān)庫集成到基類的build.gradle中,一直報錯,提示生成數(shù)據(jù)庫失敗,上面的AppDatabase_Impl文件無法生成三、使用示例
3.1 創(chuàng)建實體類 (Entity)
/**
* @Description : LocalUploadRecord 數(shù)據(jù)庫實體類,根據(jù)項目需求,定義自己的字段即可
*/
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "upload_records")
data class LocalUploadRecord(
@PrimaryKey(autoGenerate = true)
val id: Int? = null,
@ColumnInfo(name = "phone_id")
val phoneId: String,//云機(jī)ID
@ColumnInfo(name = "phone_biz_id")
val phoneBizId: String,//云機(jī)業(yè)務(wù)ID
@ColumnInfo(name = "user_id", index = true)
val userId: String,//登錄返回的用戶id
@ColumnInfo(name = "file_name")
val fileName: String,//文件名(含后綴)
@ColumnInfo(name = "file_path")
val filePath: String,//文件路徑
@ColumnInfo(name = "phone_name")
val phoneName: String,//云機(jī)名稱
@ColumnInfo(name = "file_status")
var fileStatus: FileStatus,//WAITING, UPLOADING, SUCCESS, FAILED,INSTALLING,INSTALL_FAIL,INSTALL_SUCCESS
@ColumnInfo(name = "file_time")
val fileTime: Long,//文件操作時間-時間戳:毫秒
@ColumnInfo(name = "file_size")
val fileSize: Long = 0,//文件大小,字節(jié)
@ColumnInfo(name = "err_message")
var errMessage: String = "",
@ColumnInfo(name = "reserved_field1")
var reservedField1: String = "",//預(yù)留字段1
@ColumnInfo(name = "reserved_field2")
var reservedField2: String = "",//預(yù)留字段2
@ColumnInfo(name = "reserved_field3")
var reservedField3: String = "",//預(yù)留字段3
)各注解作用:
- @Entity(tableName = "user-room"):標(biāo)記這是一個數(shù)據(jù)庫表,同時指定表名
- @PrimaryKey(autoGenerate = true):設(shè)置主鍵并啟用自動生成
- @ColumnInfo(name = "user_age"):設(shè)置列名
3.2 創(chuàng)建數(shù)據(jù)訪問對象(DAO)
創(chuàng)建一個接口定義數(shù)據(jù)庫操作: @Dao
/**
* @Description : UploadRecordDao 創(chuàng)建數(shù)據(jù)訪問對象(DAO)
* @Dao:標(biāo)記這是一個數(shù)據(jù)訪問對象接口
* @Insert、@Update、@Delete:由Room 提供的便捷注解,可以自動生成對應(yīng) SQL
* @Query:自定義 SQL 查詢,:參數(shù)名表示方法參數(shù)
*/
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import kotlinx.coroutines.flow.Flow
@Dao
interface UploadRecordDao {
/**
* 插入一條數(shù)據(jù)
*/
@Insert
fun insert(record: LocalUploadRecord): Long
/**
* 刪除最老的數(shù)據(jù)(按時間戳升序)
*/
@Query("DELETE FROM upload_records WHERE id IN (SELECT id FROM upload_records WHERE user_id = :userId ORDER BY file_time ASC LIMIT :count)")
fun deleteOldest(userId: String,count:Int)
/**
* 刪除一條記錄
*/
@Delete
fun delete(record: LocalUploadRecord)
/**
* 更新一條記錄
*/
@Update
fun update(record: LocalUploadRecord)
/**
* 根據(jù)userId獲取所有記錄
*/
@Query("SELECT * FROM upload_records WHERE user_id = :userId ORDER BY file_time DESC")
fun getRecordsByUser(userId: String): Flow<List<LocalUploadRecord>>
/**
* 根據(jù)userId和FileStatus獲取記錄
*/
@Query("SELECT * FROM upload_records WHERE user_id = :userId AND file_status IN (:statusList) ORDER BY file_time DESC")
fun getRecordsByUser(userId: String,statusList: List<FileStatus>):List<LocalUploadRecord>
/**
* 分頁獲取記錄
*/
@Query("SELECT * FROM upload_records WHERE user_id = :userId ORDER BY file_time DESC LIMIT :pageSize OFFSET :offset")
fun getRecordsByUserPaged(userId: String, pageSize: Int, offset: Int): List<LocalUploadRecord>
/**
* 根據(jù)userId查詢記錄數(shù)
*/
@Query("SELECT COUNT(*) FROM upload_records WHERE user_id = :userId")
fun getRecordCountByUser(userId: String): Int
/**
* 根據(jù)id查詢一條記錄
*/
@Query("SELECT * FROM upload_records WHERE id = :id")
// suspend fun getRecordById(id: Long): UploadRecord 低版本在Dao中不能加suspend關(guān)鍵字,會報錯,2.6.1中不會
fun getRecordById(id: Long): LocalUploadRecord
/**
* 刪除用戶的所有數(shù)據(jù)
*/
@Query("DELETE FROM upload_records WHERE user_id = :userId")
fun deleteAllByUserId(userId: String): Int
/**
* 根據(jù)id 批量刪除數(shù)據(jù)
*/
@Query("DELETE FROM upload_records WHERE id IN (:ids)")
fun deleteByIds(ids: List<Long>): Int
}各注解作用:
- @Dao:標(biāo)記這是一個數(shù)據(jù)訪問對象接口
- @Insert、@Update、@Delete:由Room 提供的便捷注解,可以自動生成對應(yīng) SQL
- @Query:自定義 SQL 查詢,:參數(shù)名表示方法參數(shù)
3.3 創(chuàng)建數(shù)據(jù)庫類
創(chuàng)建一個抽象類用于擴(kuò)展 RoomDatabase:
/**
* @Description : UploadDatabase 創(chuàng)建數(shù)據(jù)庫類
* @Database(entities = {MyUser.class}, version = 1):標(biāo)記數(shù)據(jù)庫類,指定包含的表和版本號
* Migration:定義數(shù)據(jù)庫版本遷移邏輯
* 關(guān)于數(shù)據(jù)庫遷移:
* 數(shù)據(jù)庫遷移的核心作用是在修改數(shù)據(jù)庫結(jié)構(gòu)后(比如在實體類中添加新字段或是在庫中添加新表),安全、無損地將舊版本數(shù)據(jù)庫升級到新版本,同時保留用戶的原有數(shù)據(jù)。
* 版本遷移邏輯:必須增加數(shù)據(jù)庫的版本號,并提供一個Migration對象來告訴Room如何從舊版本正確遷移到新版本。
*/
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
@Database(
entities = [LocalUploadRecord::class],
version = 1,
exportSchema = false
)
abstract class UploadDatabase : RoomDatabase() {
abstract fun uploadRecordDao(): UploadRecordDao
companion object {
@Volatile
private var INSTANCE: UploadDatabase? = null
fun getInstance(context: Context): UploadDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
UploadDatabase::class.java,
"upload_database"
).build()
INSTANCE = instance
instance
}
}
}
}各注解作用:
- @Database(entities = {MyUser.class}, version = 1):標(biāo)記數(shù)據(jù)庫類,指定包含的表和版本號
- Migration:定義數(shù)據(jù)庫版本遷移邏輯
3.4 定義一個數(shù)據(jù)庫管理類
import android.content.Context
import android.util.Log
import com.android.base.kits.KLog
import com.yixin.cloudphone.drive.data.bean.PagedResult
import com.yixin.cloudphone.drive.util.Constant
import kotlinx.coroutines.flow.Flow
/**
* @Description : UploadDatabaseManager
*/
class UploadDatabaseManager(private val context: Context) {
//每個用戶最大存儲上傳記錄個數(shù)
private val RECORD_LIMIT_COUNT=1000
private val database: UploadDatabase by lazy {
UploadDatabase.getInstance(context)
}
private val dao: UploadRecordDao by lazy {
database.uploadRecordDao()
}
/**
* 新增記錄
* 每個用戶id最多1000條數(shù)據(jù),超過的要刪除掉
*/
fun insertUploadRecord(record: LocalUploadRecord): Long {
val id=dao.insert(record)
val count=dao.getRecordCountByUser(record.userId)
if (count>RECORD_LIMIT_COUNT){
// 刪除超過1000條的最老記錄
val deleteCount=count-RECORD_LIMIT_COUNT
if(deleteCount>0){
dao.deleteOldest(record.userId,deleteCount)
KLog.d(Constant.TAG,"insertUploadRecord deleteOldest,sumSize:$count, deleteCount:$deleteCount")
}
}
return id
}
//更新上傳記錄
fun updateUploadRecord(record: LocalUploadRecord) {
dao.update(record)
}
// 獲取用戶的所有上傳記錄(Flow版本,用于觀察數(shù)據(jù)變化)
fun getUploadRecordsByUser(userId: String): Flow<List<LocalUploadRecord>> {
return dao.getRecordsByUser(userId)
}
// 根據(jù)userId和FileStatus獲取記錄
fun getUploadRecordsByUser(userId: String,statusList: List<FileStatus>): List<LocalUploadRecord>{
return dao.getRecordsByUser(userId,statusList)
}
// 分頁獲取用戶的上傳記錄
suspend fun getUploadRecordsPaged(
userId: String,
page: Int,
pageSize: Int = 20
): PagedResult<LocalUploadRecord> {
val offset = (page - 1) * pageSize
val records = dao.getRecordsByUserPaged(userId, pageSize, offset)
val totalCount = dao.getRecordCountByUser(userId)
val totalPages = (totalCount + pageSize - 1) / pageSize
return PagedResult(
data = records,
currentPage = page,
pageSize = pageSize,
totalCount = totalCount,
totalPages = totalPages
)
}
// 根據(jù)ID獲取記錄
fun getRecordById(id: Long): LocalUploadRecord? {
return dao.getRecordById(id)
}
}3.5 使用數(shù)據(jù)庫
//在Activity或viewmoudle中使用數(shù)據(jù)庫
private val roomManager: UploadDatabaseManager by lazy {
UploadDatabaseManager(VCApplication.getInstance())
}
//查詢數(shù)據(jù)庫數(shù)據(jù),使用時應(yīng)該在線程中調(diào)用,數(shù)據(jù)庫操作屬于耗時操作
viewModelScope.launch(Dispatchers.IO) {
val fileList=roomManager.getUploadRecordsByUser(userId)
}這里重點說一下,Flow中的很好用,可以看下博主示例Dao中這里的Flow<List<LocalUploadRecord>>,這樣子定義后,如果數(shù)據(jù)庫有更新,會自動收到通知,不用自己主動查詢。
到此這篇關(guān)于Android Room數(shù)據(jù)庫的基本使用的文章就介紹到這了,更多相關(guān)Android Room使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android數(shù)據(jù)庫Room的實際使用過程總結(jié)
- Android Room數(shù)據(jù)庫自動升級與遷移的策略
- Android使用Room數(shù)據(jù)庫解決本地持久化的操作
- Android Room數(shù)據(jù)庫容易遇到的問題以及解決方法
- Android?Room數(shù)據(jù)庫加密詳解
- Android room數(shù)據(jù)庫使用詳解
- Android kotlin+協(xié)程+Room數(shù)據(jù)庫的簡單使用
- Android Room數(shù)據(jù)庫多表查詢的使用實例
- 詳細(xì)介紹Android-Room數(shù)據(jù)庫的使用
相關(guān)文章
Android學(xué)習(xí)筆記之Shared Preference
在之前遇到有個需求是要改settings里面自動轉(zhuǎn)屏的首選項,于是就學(xué)習(xí)了下Shared Preference。Shared Preference是一種簡單的、輕量級的鍵/值對機(jī)制,用于保存原始應(yīng)用程序數(shù)據(jù),最常見的就是首選項2013-09-09
android跑馬燈出現(xiàn)重復(fù)跳動以及不滾動問題的解決方法
這篇文章主要介紹了android跑馬燈出現(xiàn)重復(fù)跳動以及不滾動問題的解決方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
開源電商app常用標(biāo)簽"hot"之第三方開源LabelView
這篇文章主要介紹了開源電商app常用標(biāo)簽"hot"之第三方開源LabelView,對開源電商app相關(guān)資料感興趣的朋友一起學(xué)習(xí)吧2015-12-12
Android基于BaseExpandableListAdapter實現(xiàn)的二級列表仿通話記錄功能詳解
這篇文章主要介紹了Android基于BaseExpandableListAdapter實現(xiàn)的二級列表仿通話記錄功能,結(jié)合具體實例形式分析了Android實現(xiàn)通話記錄功能的布局與功能相關(guān)操作技巧,需要的朋友可以參考下2017-07-07

