Android compose Room Sqlite 应用 (注入式)

1.添加room库

project build.gradle.kts

Kotlin 复制代码
    //plugins
    kotlin("plugin.serialization") version "2.1.0"
    id("androidx.room") version "2.7.1" apply false

app build.gradle.kts

Kotlin 复制代码
    //plugins 
    kotlin("plugin.serialization")
    id("androidx.room")
    kotlin("kapt")
Kotlin 复制代码
//dependencies
//room
    var room_version = "2.7.1"
    implementation("androidx.room:room-ktx:$room_version")
    implementation("androidx.room:room-runtime:$room_version")
    kapt("androidx.room:room-compiler:$room_version")

//inject
    implementation("io.insert-koin:koin-android:4.0.3")
    implementation("io.insert-koin:koin-androidx-compose:4.0.3")
    implementation("io.insert-koin:koin-androidx-compose-navigation:4.0.3")

//serialization
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0")

2.创建数据库

//Entities

Kotlin 复制代码
@Entity(tableName = "banner")
data class BannerEntity(
    @PrimaryKey(autoGenerate = true) val id: Int = 0,
    val url: String
)


@Entity(tableName = "category")
data class CategoryEntity(
    @PrimaryKey val id: Int,
    val title: String
)

@Entity(tableName = "item")
data class ItemEntity(
    @PrimaryKey(autoGenerate = true) val id: Int = 0,
    val title: String,
    val description: String,
    val price: Int,
    val rating: Double,
    val showRecommended: Boolean,
    val categoryId: Int
)

@Entity(tableName = "pic_url")
data class PicUrlEntity(
    @PrimaryKey(autoGenerate = true) val id: Int = 0,
    val itemId: Int,
    val url: String
)

data class ItemWithPics(
    @Embedded val item: ItemEntity,
    @Relation(
        parentColumn = "id",
        entityColumn = "itemId"
    )
    val pics: List<PicUrlEntity>
)


data class ItemWithCategory(
    @Embedded val item: ItemEntity,
    @Relation(
        parentColumn = "categoryId",
        entityColumn = "id"
    )
    val category: CategoryEntity
)

data class ItemFull(
    @Embedded val item: ItemEntity,
    @Relation(
        parentColumn = "id",
        entityColumn = "itemId"
    )
    val pics: List<PicUrlEntity>,

    @Relation(
        parentColumn = "categoryId",
        entityColumn = "id"
    )
    val category: CategoryEntity
)

//Daoes

Kotlin 复制代码
@Dao
interface BannerDao {
    @Insert
    suspend fun insertAll(banners: List<BannerEntity>)

    @Query("SELECT * FROM banner")
    suspend fun getAll(): List<BannerEntity>
}

@Dao
interface CategoryDao {
    @Insert
    suspend fun insertAll(categories: List<CategoryEntity>)

    @Query("SELECT * FROM category")
    suspend fun getAll(): List<CategoryEntity>
}

@Dao
interface ItemDao {
    @Insert
    suspend fun insertAll(items: List<ItemEntity>)

    @Transaction
    @Query("SELECT * FROM item")
    suspend fun getItemsWithPics(): List<ItemWithPics>

    @Transaction
    @Query("SELECT * FROM item WHERE showRecommended = 1")
    suspend fun getRecommendedItems(): List<ItemWithPics>

    @Transaction
    @Query("SELECT * FROM item WHERE categoryId = :categoryId")
    suspend fun getItemsByCategory(categoryId: Int): List<ItemWithPics>

    @Transaction
    @Query("SELECT * FROM item")
    suspend fun getFullItemData(): List<ItemFull>
}


@Dao
interface PicUrlDao {
    @Insert
    suspend fun insertAll(picUrls: List<PicUrlEntity>)

    @Query("SELECT * FROM pic_url WHERE itemId = :itemId")
    suspend fun getPicsByItemId(itemId: Int): List<PicUrlEntity>
}

//Databases

Kotlin 复制代码
@Database(entities = [
    BannerEntity::class,
    CategoryEntity::class,
    ItemEntity::class,
    PicUrlEntity::class
], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun bannerDao(): BannerDao
    abstract fun categoryDao(): CategoryDao
    abstract fun itemDao(): ItemDao
    abstract fun picUrlDao(): PicUrlDao

    companion object {
        @Volatile
        private var INSTANCE: AppDatabase? = null

        private const val DATABASE_NAME = "database.db"

        fun getInstance(context: Context): AppDatabase {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
            }
        }

        private fun buildDatabase(context: Context): AppDatabase {
            return Room.databaseBuilder(
                context.applicationContext,
                AppDatabase::class.java,
                DATABASE_NAME
            ).createFromAsset(DATABASE_NAME)
                .build()
        }
    }
}

//数据库文件

在绑定文件中。

  1. 配置模块,定义 Application
Kotlin 复制代码
val appModule = module {
    single { AppDatabase.getInstance(get()) }
    viewModelOf(::DashboardViewModel)
}
Kotlin 复制代码
class OnlineShopApplication: Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin {
            androidContext(this@OnlineShopApplication)
            modules(appModule)
        }
    }
}

在AndroidManifest.xml中添加application的使用代号

Kotlin 复制代码
    <application
        android:name=".OnlineShopApplication" 
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.OnlineShopApp"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.OnlineShopApp">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

4.创建DashboardViewModel

Kotlin 复制代码
class DashboardViewModel(
    private val appDatabase: AppDatabase
): ViewModel() {
    private val _mState = MutableStateFlow(DashboardState())
    val mState = _mState.onStart {
        initBanners()
        initCategories()
        initItemWithPics()
    }.stateIn(
        viewModelScope,
        SharingStarted.WhileSubscribed(5000),
        _mState.value
    )


    private fun initBanners(){
        viewModelScope.launch {
            val bannerEntities = appDatabase.bannerDao().getAll()
            _mState.update {
                it.copy(banners = bannerEntities)
            }
        }
    }

    private fun initCategories(){
        viewModelScope.launch {
            val categoryEntities = appDatabase.categoryDao().getAll()
            _mState.update {
                it.copy(categories = categoryEntities)
            }
        }
    }

    private fun initItemWithPics(){
        viewModelScope.launch {
            val recommandItems = appDatabase.itemDao().getRecommendedItems()
            _mState.update {
                it.copy(itemWithPics = recommandItems)
            }
        }
    }
}

5.创建DashboardState

Kotlin 复制代码
data class DashboardState (
    val banners:List<BannerEntity> = emptyList(),
    val categories:List<CategoryEntity> = emptyList(),
    val itemWithPics:List<ItemWithPics> = emptyList(),
)

6.使用viewmodel

在@Compose中

Kotlin 复制代码
    // val isPreview = false
    
    val viewModel = if (isPreview) injectPreviewModel() else koinViewModel()
    val mState by viewModel.mState.collectAsStateWithLifecycle()

    //使用时
    //mState.banners
Kotlin 复制代码
@Composable
fun injectPreviewModel(): DashboardViewModel {
    val context = LocalContext.current
    return remember {
        DashboardViewModel(
            AppDatabase.getInstance(context)
        )
    }
}

7.当viewmodel中带有参数时。

Kotlin 复制代码
//定义带有参数的viewmodel时

class DetailViewModel(
    private val appDatabase: AppDatabase,
    private val param: Route.Detail
) : ViewModel() {


}

在@Compose使用时

Kotlin 复制代码
    val viewModel =
        if (isPreview) injectPreviewModel(param) else koinViewModel { parameterSetOf(param)}

    val mState by viewModel.mState.collectAsStateWithLifecycle()
相关推荐
九皇叔叔1 小时前
【第二章】Redis基础入门:Redis是什么、为什么快以及核心特性详解
数据库·redis·缓存
云和恩墨1 小时前
删库不跑路,回滚极速触达——zData S“旁路日志”持续保护原理深剖
数据库
MetaLite2 小时前
SpringBoot接口分层规范-外网网关内部服务与参数边界
java·数据库·spring boot
Wang's Blog4 小时前
Java框架快速入门: Spring Security+OAuth2之元注解简化权限表达式
java·数据库·spring
天空之城--4 小时前
Android逆向安全合规接单指南
android·安全
蓝速科技6 小时前
医院导诊 AI 数字人一体机场景适配与落地指南丨蓝速科技
运维·数据库·人工智能·科技·自然语言处理·技术分享
QYR-分析6 小时前
重轨受电弓行业深度报告:市场格局、技术迭代与发展前景
大数据·数据库·人工智能
消失的旧时光-19436 小时前
Android 系统层扫盲 09:AMS、ATMS、WMS、PMS 到底分别管什么?
android·wms·pms·ams·aosp·atms
泡泡鱼(敲代码中)6 小时前
MySQL基础学习笔记:从数据模型到DDL全掌握
开发语言·数据库·笔记·学习·mysql
Godikov6 小时前
Android 系统级设备应用踩坑实录:sharedUserId 签名、SDK 授权失败 -4、开机自启与 U 盘 OTA 升级
android