Room数据库的使用及原理详解

一、Room数据库的大三组件

Database:即数据库。扩展了RoomDatabase的抽象类。可以通过Room获得它的一个实例。databaseBuilder或Room.inMemoryDatabaseBuilder。

Dao:数据访问对象,是Room的主要组件,负责定义访问数据库的方法。

Entity:实体类,代表一个表结构。

二、实现原理

Room数据库实现原理

在数据库DataBase中想要访问数据库的操作,需要获取操作Dao的对象,而Dao会给DataBase返回一个entity的对象。当我们用Room数据库进行存储时,其实存储的并非要存储的具体对象,深度ip转换器而是对象对应的一些信息。因此,我们引入Repository仓库类用于操作Room,而我们给外部暴露的是viewModel类,因此,viewModel需要持有Repository对象。此外,Repository与viewModel之间也需要context传递上下文信息。

三、优点

针对 SQL 查询的编译时验证

可最大限度减少重复和容易出错的样板代码的方便注解

简化了数据库迁移路径

四、使用方式(以创建一个相册数据库为例)

声明依赖项

     def room_version = "2.3.0"

     implementation "androidx.room:room-runtime:$room_version"

     annotationProcessor "androidx.room:room-compiler:$room_version"

创建相册表实体类Entity

import androidx.room.Entity

import androidx.room.PrimaryKey

const val ALBUM_TYPE_IMAGE = 0

const val ALBUM_TYPE_VIDEO = 1

//默认表名就是类名

//@Entity(tableName = "album_table")

@Entity

data class Album (

    @PrimaryKey(autoGenerate = true)//主键自增长取消,因为是string类型

    val id:Int,

    var albumName:String,

    //@ColumnInfo(name ="cover_url") 表名和属性名的转换

    var coverUrl:String,

    var number:Int,

    val type:Int = ALBUM_TYPE_IMAGE

)

//缩略图表

@Entity

data class ThumbImage(

    @PrimaryKey(autoGenerate = false)

    val imageName:String,

    //外键

    val albumId: Int

)

创建Dao

import androidx.room.*

import java.util.concurrent.Flow

@Dao

interface AlbumDao {

    //创建相册 数据库操作都耗时suspend

    //@Insert(onConflict = OnConflictStrategy.)解决冲突

    @Insert

    fun insertAlbum(album: Album)

    //删除一个相册

    @Delete

    fun deleteAlbum(album: Album)

    //删除多个相册 可变数组

    @Delete

    fun deleteAlbums(vararg album: Album)

    //更新相册

    @Update

    fun updateAlbum(album: Album)

    //查询所有相册信息

    @Query("select * from Album where type = :type")

    fun getAllAlbumsWithType(type:Int):kotlinx.coroutines.flow.Flow>

    /**------------------------相片--------------------------**/

    //插入一张图

    @Insert

    fun insertImage(thumbImage: ThumbImage)

    //插入多张图

    @Insert

    fun insertImages(vararg thumbImage: ThumbImage)

    //删除一张图

    @Delete

    fun deleteImage(thumbImage: ThumbImage)

    //删除多张图

    @Delete

    fun deleteImages(vararg thumbImage: ThumbImage)

}

创建数据库DataBase

import android.content.Context

import androidx.room.Database

import androidx.room.Room

import androidx.room.RoomDatabase

@Database(

    entities = [Album::class,ThumbImage::class],

    version = 1,

    exportSchema = false //是否导出

    )

abstract class AlbumDatabase:RoomDatabase() {

    //获取一系列数据库访问的接口实现类

    abstract fun albumDao():AlbumDao

    //访问静态属性,提供单例对象

    //有就返回,没有就加锁再返回

    companion object{

        private var INSTANCE:AlbumDatabase ? = null

        fun getInstance(context: Context):AlbumDatabase{

            if (INSTANCE != null){

                return INSTANCE!!

            }

            synchronized(this){

                if (INSTANCE == null){

                    INSTANCE = Room.databaseBuilder(

                        context,

                        AlbumDatabase::class.java,

                        "album_db"

                    ).build()

                }

                return INSTANCE!!

            }

        }

    }

}

5.创建Repository给viewModel提供访问方法

import android.content.Context

import kotlinx.coroutines.flow.Flow

class Repository(context: Context) {

    private var albumDao:AlbumDao

    init {

        albumDao = AlbumDatabase.getInstance(context).albumDao()

    }

    //加载相册

    suspend fun loadAlbumWithType(type:Int): Flow> {

        return albumDao.getAllAlbumsWithType(type)

    }

    //插入相册

    suspend fun addAlbum(album: Album){

        albumDao.insertAlbum(album)

    }

}

viewModel持有Repository,给外部提供操作方法

package com.example.privatealbum.db

import android.app.Application

import android.util.Log

import androidx.lifecycle.AndroidViewModel

import androidx.lifecycle.MutableLiveData

import androidx.lifecycle.viewModelScope

import com.example.privatealbum.DEFAULT_COVER_URL

import kotlinx.coroutines.Dispatchers

import kotlinx.coroutines.flow.collectLatest

import kotlinx.coroutines.launch

//与viewModel的区别是强制传一个参数,拥有application即拥有context

class SharedViewModel(application: Application)

    :AndroidViewModel(application){

    //保存所有相册信息

    var imageAlbumList = MutableLiveData>(emptyList())

    var videoAlbumList = MutableLiveData>(emptyList())

    //仓库对象

    val repository = Repository(application.applicationContext)

    //保存当前添加相册的类型

    var type = ALBUM_TYPE_IMAGE

    //相册删除按钮默认不显示 有内容显示

    var shouldShowDeleteInAlbum = MutableLiveData(false)

    private var deleteAlbumList = arrayListOf()

    //添加需要删除的相册

    fun addAlbumToDeleteList(album: Album){

        deleteAlbumList.add(album)

        shouldShowDeleteInAlbum.postValue(true)

    }

    fun deleteAlbumFromDeleteList(album: Album){

        deleteAlbumList.remove(album)

        shouldShowDeleteInAlbum.postValue(deleteAlbumList.size > 0)

    }

    //获取相册

    fun loadAlbumsWithType(albumType:Int){

        viewModelScope.launch(Dispatchers.IO) {

            val

你可能感兴趣的:(数据库)