当前位置: 首页 > news >正文

Android在KSP中简单使用Room

Android在KSP中简单使用Room

最近下载了最新版Studio,好多依赖和配置都需要升级,之前使用过room封装数据库工具类,最近在整理ksp相关,于是把room也升级了,简单记录一下升级过程,直接上代码。

1.添加KSP依赖配置:

#KSP
ksp = "2.1.10-1.0.29"

ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }

在这里插入图片描述

2.项目的依赖配置:

plugins {
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.android.library).apply(false)
    alias(libs.plugins.kotlin.android) apply false
    alias(libs.plugins.ksp).apply(false)
}

在这里插入图片描述

3.app的build.gradle配置:

plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.android)
    alias(libs.plugins.ksp)
}

在这里插入图片描述

4.添加room配置:

#Room
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
util-codex = { group = "com.blankj", name= "utilcodex", version.ref = "utilcodex" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
android-library = { id = "com.android.library", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
[bundles]
room = [
    "androidx-room-ktx",
    "androidx-room-runtime",
]

在这里插入图片描述

在这里插入图片描述

5.在build.gradle添加room:

api(libs.bundles.room)
ksp(libs.androidx.room.compiler)

在这里插入图片描述

6.room数据库生成文件路径:

6.1 路径配置:

ksp {
    arg("room.schemaLocation", "$projectDir/schemas")
}
    defaultConfig {
        applicationId = "com.example.ksproomdemo"
        minSdk = 24
        targetSdk = 36
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        ksp {
            arg("room.schemaLocation", "$projectDir/schemas")
        }
    }

在这里插入图片描述

6.2. room对应的jvm版本:

compileOptions {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
    jvmTarget = "17"
}
ksp {
    arg("jvmTarget", "17")
}

6.3 生成的数据库文件如下:

{
  "formatVersion": 1,
  "database": {
    "version": 1,
    "identityHash": "1599160ffa834f06d3bdbe0680959e41",
    "entities": [
      {
        "tableName": "User",
        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `name` TEXT NOT NULL, `sex` TEXT NOT NULL, `email` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)",
        "fields": [
          {
            "fieldPath": "userId",
            "columnName": "userId",
            "affinity": "TEXT",
            "notNull": true
          },
          {
            "fieldPath": "name",
            "columnName": "name",
            "affinity": "TEXT",
            "notNull": true
          },
          {
            "fieldPath": "sex",
            "columnName": "sex",
            "affinity": "TEXT",
            "notNull": true
          },
          {
            "fieldPath": "email",
            "columnName": "email",
            "affinity": "TEXT",
            "notNull": true
          },
          {
            "fieldPath": "id",
            "columnName": "id",
            "affinity": "INTEGER",
            "notNull": true
          }
        ],
        "primaryKey": {
          "autoGenerate": true,
          "columnNames": [
            "id"
          ]
        },
        "indices": [],
        "foreignKeys": []
      }
    ],
    "views": [],
    "setupQueries": [
      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1599160ffa834f06d3bdbe0680959e41')"
    ]
  }
}

在这里插入图片描述

7.布局文件:

<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">

    <TextView
        android:id="@+id/tv_add"
        android:layout_width="200dp"
        android:layout_height="40dp"
        android:text="添加数据"
        android:textColor="@color/white"
        android:textSize="18sp"
        android:gravity="center"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginEnd="20dp"
        android:background="@color/design_default_color_primary"/>

    <TextView
        android:id="@+id/tv_update"
        android:layout_width="200dp"
        android:layout_height="40dp"
        android:text="修改数据"
        android:textColor="@color/white"
        android:textSize="18sp"
        android:gravity="center"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_add"
        android:layout_marginTop="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginEnd="20dp"
        android:background="@color/design_default_color_primary"/>

    <TextView
        android:id="@+id/tv_query"
        android:layout_width="200dp"
        android:layout_height="40dp"
        android:text="查询数据"
        android:textColor="@color/white"
        android:textSize="18sp"
        android:gravity="center"
        android:singleLine="true"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_update"
        android:layout_marginTop="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginEnd="20dp"
        android:background="@color/design_default_color_primary"/>
    <TextView
        android:id="@+id/tv_delete"
        android:layout_width="200dp"
        android:layout_height="40dp"
        android:text="删除数据"
        android:textColor="@color/white"
        android:textSize="18sp"
        android:gravity="center"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_query"
        android:layout_marginTop="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginEnd="20dp"
        android:background="@color/design_default_color_primary"/>
    <TextView
        android:id="@+id/tv_delete_users"
        android:layout_width="200dp"
        android:layout_height="40dp"
        android:text="删除多个数据"
        android:textColor="@color/white"
        android:textSize="18sp"
        android:gravity="center"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_delete"
        android:layout_marginTop="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginEnd="20dp"
        android:background="@color/design_default_color_primary"/>

    <TextView
        android:id="@+id/tv_delete_all"
        android:layout_width="200dp"
        android:layout_height="40dp"
        android:text="删除所有数据"
        android:textColor="@color/white"
        android:textSize="18sp"
        android:gravity="center"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_delete_users"
        android:layout_marginTop="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginEnd="20dp"
        android:background="@color/design_default_color_primary"/>

</androidx.constraintlayout.widget.ConstraintLayout>

8.数据库工具类RoomUtils:

package com.example.db

import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.example.app.RoomApp
import com.example.ksproomdemo.bean.User
import com.example.ksproomdemo.dao.UserDao

/**
 * @author: njb
 * @date:   2025/3/30 1:25
 * @desc:   描述
 */
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}
class RoomUtils private constructor(){
    private val database: AppDatabase by lazy {
        Room.databaseBuilder(
            RoomApp.instance.applicationContext,
            AppDatabase::class.java, "app-database"
        ).build()
    }

    companion object {
        @Volatile
        private var instance: RoomUtils? = null

        fun getInstance(): RoomUtils {
            return instance ?: synchronized(this) {
                instance ?: RoomUtils().also { instance = it }
            }
        }
    }

    private val userRepository: UserRepository by lazy {
        UserRepository(database.userDao())
    }

    suspend fun insertUser(user: User) {
        userRepository.insertUser(user)
    }

    suspend fun updateUser(user: User) {
        userRepository.updateUser(user)
    }

    suspend fun deleteUser(user: User) {
        userRepository.deleteUser(user)
    }

    suspend fun getAllUsers(): List<User> {
        return userRepository.getAllUsers()
    }

    suspend fun deleteUsers(user: List<User>) {
        return userRepository.deleteUsers(user)
    }


    suspend fun deleteAllUser() {
        userRepository.deleteAllUser()
    }
}

9.UserRepository:

package com.example.db

import com.example.ksproomdemo.bean.User
import com.example.ksproomdemo.dao.UserDao
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

/**
 * @author: njb
 * @date:   2025/3/30 1:26
 * @desc:   描述
 */
class UserRepository (private val userDao: UserDao){
    suspend fun insertUser(user: User) {
        withContext(Dispatchers.IO) {
            userDao.insertAll(user)
        }
    }

    suspend fun updateUser(user: User) {
        withContext(Dispatchers.IO) {
            userDao.updateUser(user)
        }
    }

    suspend fun deleteUser(user: User) {
        withContext(Dispatchers.IO) {
            userDao.delete(user)
        }
    }

    suspend fun getAllUsers(): List<User> {
        return withContext(Dispatchers.IO) {
            userDao.getAll()
        }
    }

    suspend fun deleteUsers(user: List<User>) {
        withContext(Dispatchers.IO) {
            userDao.deleteUsers(user)
        }
    }

    suspend fun deleteAllUser() {
        withContext(Dispatchers.IO) {
            userDao.deleteAllUserInfo()
        }
    }
}

10.Dao和实体类:

package com.example.ksproomdemo.dao

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.example.ksproomdemo.bean.User

/**
 * @author: njb
 * @date:   2025/3/30 1:06
 * @desc:   描述
 */
@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    suspend fun getAll(): List<User>

    @Query("SELECT * FROM user WHERE id IN (:userIds)")
    suspend fun loadAllByIds(userIds: IntArray): List<User>

    @Query("SELECT * FROM user WHERE name LIKE :name")
    suspend fun findByName(name: String): User?

    @Query("SELECT *FROM user WHERE id LIKE:userId")
    suspend fun findById(userId: Int): User?

    @Update
    suspend fun updateUser(user: User)

    @Insert
    suspend fun insertAll(users: User)

    @Delete
    suspend fun delete(user: User)

    @Delete
    suspend fun deleteUsers(user: List<User>)

    @Query("DELETE FROM User")
    suspend fun deleteAllUserInfo()
}
package com.example.ksproomdemo.bean

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

/**
 * @author: njb
 * @date:   2025/3/30 1:24
 * @desc:   描述
 */
@Entity(tableName = "User")
data class User(
    var userId: String = "",
    @ColumnInfo(name = "name") var name: String = "",
    @ColumnInfo(name = "sex") var sex: String = "",
    @ColumnInfo(name = "email") var email: String = "",
){
    @PrimaryKey(autoGenerate = true)
    var id: Long = 0
}

11.测试代码:

package com.example.ksproomdemo

import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.SnackbarUtils
import com.blankj.utilcode.util.ToastUtils
import com.example.db.RoomUtils
import com.example.ksproomdemo.bean.User
import com.example.ksproomdemo.databinding.ActivityMainBinding
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class MainActivity : AppCompatActivity() {
    private lateinit var roomUtils: RoomUtils
    private lateinit var binding:ActivityMainBinding
    private val TAG = "Mainivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        initView()
        initListener()
    }

    private fun initView() {
        roomUtils = RoomUtils.getInstance()
    }

    private fun initListener() {
        binding.tvAdd.setOnClickListener {
            lifecycleScope.launch {
                val user = User("18","张三","男","zhangsan@qq.com")
                withContext(Dispatchers.IO) {
                    roomUtils.insertUser(user)
                    LogUtils.d(TAG, "----添加用户数据----$user")
                }
                Snackbar.make(binding.tvAdd,user.toString(),Snackbar.LENGTH_LONG).show()
            }
        }
        binding.tvUpdate.setOnClickListener {
            lifecycleScope.launch {
                val user = User("12","Tom","女","ousi@example.com")
                withContext(Dispatchers.IO){
                    roomUtils.updateUser(user)
                    LogUtils.d(TAG, "----更新用户数据----$user")
                }
                Snackbar.make(binding.tvUpdate,user.toString(),Snackbar.LENGTH_LONG).show()
            }
        }
        binding.tvQuery.setOnClickListener {
            lifecycleScope.launch {
                val user = withContext(Dispatchers.IO){
                    RoomUtils.getInstance().getAllUsers()
                }
                LogUtils.d(TAG, "----查询用户数据----$user")
                Snackbar.make(binding.tvQuery,user.toString(),Snackbar.LENGTH_LONG).show()
            }
        }
        binding.tvDelete.setOnClickListener {
            lifecycleScope.launch {
                val user = User("18","张三","男","zhangsan@qq.com")
                withContext(Dispatchers.IO){
                    RoomUtils.getInstance().deleteUser(user)
                }
                LogUtils.d(TAG, "----删除一条用户数据----$user")
                Snackbar.make(binding.tvDelete,user.toString(),Snackbar.LENGTH_LONG).show()
            }
        }
        binding.tvDeleteUsers.setOnClickListener {
            lifecycleScope.launch {
                val user = roomUtils.getAllUsers()
                val user1 : List<User>
                // 删除所有用户
                withContext(Dispatchers.IO) {
                    roomUtils.deleteUsers(user)
                    user1 = roomUtils.getAllUsers()
                }
                LogUtils.d(TAG, "===删除多个用户数据===$user1")
                Snackbar.make(binding.tvDelete,user1.toString(),Snackbar.LENGTH_LONG).show()
            }
        }
        binding.tvDeleteAll.setOnClickListener {
            lifecycleScope.launch {
                val user : List<User>
                // 删除所有用户
                withContext(Dispatchers.IO) {
                    roomUtils.deleteAllUser()
                    user = roomUtils.getAllUsers()
                }
                LogUtils.d(TAG, "===删除所有用户数据===$user")
                Snackbar.make(binding.tvDelete,user.toString(),Snackbar.LENGTH_LONG).show()
            }
        }
    }
}

12.日志打印:

2025-03-30 22:53:13.383  3712-3760  Mainivity               com.example.ksproomdemo              D  ----添加用户数据----User(userId=18, name=张三, sex=, email=zhangsan@qq.com)

2025-03-30 22:53:26.322  3712-3760  Mainivity               com.example.ksproomdemo              D  ----更新用户数据----User(userId=12, name=Tom, sex=, email=ousi@example.com)

2025-03-30 22:53:37.349  3712-3712  Mainivity               com.example.ksproomdemo              D  ----查询用户数据----[User(userId=18, name=张三, sex=, email=zhangsan@qq.com), User(userId=18, name=张三, sex=, email=zhangsan@qq.com), User(userId=18, name=张三, sex=, email=zhangsan@qq.com)]

2025-03-30 22:53:49.061  3712-3712  Mainivity               com.example.ksproomdemo              D  ----删除一条用户数据----User(userId=18, name=张三, sex=, email=zhangsan@qq.com)

2025-03-30 22:53:58.775  3712-3712  Mainivity               com.example.ksproomdemo              D  ===删除多个用户数据===[]
  Mainivity               com.example.ksproomdemo              D  ===删除所有用户数据===[]

13.实现效果如下:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

14.总结:

  • ksp要添加相应插件和依赖,配置方式有所改变.
  • ksp中room的路径要配置正确.
  • ksp中jvm版本要对应.
  • 升级到最新的gradle后compileSdk版本要使用最新的.

15.项目源码:

https://gitee.com/jackning_admin/ksproom-demo


文章转载自:
http://aviva.gbfuy28.cn
http://auckland.gbfuy28.cn
http://chid.gbfuy28.cn
http://balconet.gbfuy28.cn
http://apparat.gbfuy28.cn
http://aletophyte.gbfuy28.cn
http://bert.gbfuy28.cn
http://beauteously.gbfuy28.cn
http://backbench.gbfuy28.cn
http://blackness.gbfuy28.cn
http://botch.gbfuy28.cn
http://ambagious.gbfuy28.cn
http://burgundian.gbfuy28.cn
http://authorware.gbfuy28.cn
http://baal.gbfuy28.cn
http://bella.gbfuy28.cn
http://chetah.gbfuy28.cn
http://cavu.gbfuy28.cn
http://avarice.gbfuy28.cn
http://aneurysm.gbfuy28.cn
http://baalism.gbfuy28.cn
http://aganippe.gbfuy28.cn
http://bangka.gbfuy28.cn
http://blastosphere.gbfuy28.cn
http://cajan.gbfuy28.cn
http://arthral.gbfuy28.cn
http://bushfighting.gbfuy28.cn
http://bilboa.gbfuy28.cn
http://chatelain.gbfuy28.cn
http://braunschweiger.gbfuy28.cn
http://www.dtcms.com/a/100285.html

相关文章:

  • Vue.js的多个组件过渡:实现组件的动态切换
  • 互联网的组成
  • C语言信号量使用案例
  • 每日小积累day1
  • TDengine tar.gz和docker两种方式安装和卸载
  • 【蓝桥杯速成】| 16.完全背包组合|排序
  • Rollup系列之安装和入门
  • MQTT之重复消息(6、在项目中遇到的问题)
  • Pandas **Series**
  • 传统策略梯度方法的弊端与PPO的改进:稳定性与样本效率的提升
  • 【干货】前端实现文件保存总结
  • rce操作
  • 唤起“堆”的回忆
  • 基于自定义注解+反射+AOP+Redis的通用开关设计:在投行交易与风控系统的落地实践
  • golang 的reflect包的常用方法
  • 低速通信之王:LIN总线工作原理入门
  • 创作领域“<em >彩</em><em>票</em><em>导</em><em>师</em><em>带</em><em>玩</em><em>群
  • SvelteKit 最新中文文档教程(15)—— 链接选项
  • C语言的sprintf函数使用
  • Rust 为什么不适合开发 GUI
  • Java后端开发: 如何安装搭建Java开发环境《安装JDK》和 检测JDK版本
  • 【Tauri2】008——简单说说配置文件
  • QtWebApp使用
  • .Net framework 3.5怎样离线安装
  • Redis-09.Redis常用命令-通用命令
  • Python练习
  • QXmpp入门
  • 前端学习日记--JavaScript
  • 大模型生成吉卜力风格艺术:技术与魔法的完美结合
  • 【附JS、Python、C++题解】Leetcode面试150题(12)多数问题