目录

Gradle 概述

AS Gradle 8.0 配置说明

1)项目 settings.gradle

2)项目 build.gradle

3)子模块 hawkysdk-realm

3.1 build.gradle

3.2 Realm 表

3.3 Realm Dao

3.4 RealmCallback DB操作回调

3.5 HawkyRealm DB配置初始化

4)子模块 app

4.1 build.gradle

4.2 RealmApplication

4.3 User 实体类

4.4 MainActivity 测试类

4.5 activity_main 布局文件

小结


Gradle 概述

Gradle 是一个基于 Apache Ant 和 Apache Maven 概念的项目自动化构建开源工具。它使用一种基于 Groovy 的特定领域语言 (DSL) 来声明项目设置,也增加了基于 Kotlin 语言的 kotlin-based DSL。

查看版本路径:Gradle 版本可在 gradle-wrapper.properties 查看(一般检查本地是否有下载对应的版本,没有就会按照distributionUrl定义的路径下载对应的 Gradle 版本),也可在 Project Structure  查看 Gradle 版本及 Gradle 插件版本(classpath 'com.android.tools.build:gradle:8.0.0' 默认已内置,无需再配置)。

同 Gradle 插件的本质区别:Gradle 是提供 DSL 语言脚本,供项目配置使用;Gradle 插件是支持脚本执行的环境。

AS Gradle 8.0 配置说明

最近由于项目需要,使用到了 Realm 数据库,而 Gradle 版本升级到了 8.0,Gradle 插件版本也升级到了 8.0.0。所以打算对本次升级结合 Realm 的具体使用 以及编译过程中遇到的坑做个总结。

1)项目 settings.gradle

说明:用于定义项目级代码库设置及所包含的模块。--原项目 build.gradle 中的部分配置拆分至新增的 settings.gradle 文件中。

//  New Version:buildscript --> pluginManagement 插件管理
pluginManagement {repositories {// 下载 Gradle 插件 的依赖仓库google()mavenCentral()gradlePluginPortal()}
}// New Version: allprojects --> dependencyResolutionManagement 依赖项解析管理
dependencyResolutionManagement {/*** 设置存储库模式(原 allprojects 是没有这一项的):* PREFER_PROJECT:解析依赖库时, 优先使用本地仓库* FAIL_ON_PROJECT_REPOS:解析依赖库时, 强行使用远程仓库*/repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositories {google()mavenCentral()}
}// 项目工程的名字,可不写
// rootProject.name = "Realm"// include modules
include ':app'
include ':hawkybase'
include ':hawkysdk-realm'// project paths
project(':hawkybase').projectDir = new File(settingsDir, '../../hawky-base-android/hawkybase')
project(':hawkysdk-realm').projectDir = new File(settingsDir, '../../hawky-sdk-android/hawkysdk-realm')

2)项目 build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.// 这里仍然可以使用老的 buildscript,来配置需要的插件
buildscript {ext.kotlin_version = '1.8.0'dependencies {classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"classpath "io.realm:realm-gradle-plugin:10.15.1"}repositories {mavenCentral()}
}plugins {// 项目build配置应声明为false,告诉 Gradle 不要将插件应用到当前项目id 'com.android.application' version '8.0.0' apply falseid 'com.android.library' version '8.0.0' apply falseid 'org.jetbrains.kotlin.android' version "$kotlin_version" apply false
}// 定义扩展参数,可全局配置使用
ext {compileSdkVersion = 33//...
}

3)子模块 hawkysdk-realm

3.1 build.gradle

// 必须放前面
plugins {// 相当于 apply plugin: 'com.android.library'id 'com.android.library'id 'org.jetbrains.kotlin.android'id 'kotlin-kapt'id 'realm-android'
}android {namespace 'com.hawky.hawkysdk.realm'compileSdk rootProject.ext.compileSdkVersiondefaultConfig {minSdk 24targetSdk 33testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"consumerProguardFiles "consumer-rules.pro"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_17targetCompatibility JavaVersion.VERSION_17}kotlinOptions {jvmTarget = '17'}
}dependencies {implementation "androidx.core:core-ktx:$kotlin_version"implementation 'androidx.appcompat:appcompat:1.4.1'implementation 'com.google.android.material:material:1.5.0'implementation project(path: ':hawkybase')testImplementation 'junit:junit:4.13.2'androidTestImplementation 'androidx.test.ext:junit:1.1.3'androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

3.2 Realm 表

// 定义Person 表,主键 id
open class PersonModel : RealmObject() {@PrimaryKeyvar id: Long = 0var name: String? = nullvar email: String? = null
}

3.3 Realm Dao

package com.hawky.hawkysdk.realm.realmdaoimport com.hawky.hawkysdk.realm.realmmodel.PersonModel
import io.realm.Realm
import io.realm.Sort
import io.realm.exceptions.RealmPrimaryKeyConstraintExceptionobject PersonDao {/*** 保存数据* 注意:1)无论 copyToRealm 还是 insert 都必须设置主键,否则再次执行会报 “existing primary key value”*     2)Realm对象只能在它创建的线程上访问(“Realm access from incorrect thread”)*/fun savePerson(person: PersonModel, callback: RealmCallback?) {val realm = Realm.getDefaultInstance()//========= 方式1:手动使用事务 ====================///*realm.beginTransaction()// insert 速度快而且没有返回值,一般用在数据修改少、查询多的场景。realm.insert(person)realm.commitTransaction()*///========== 方式2:executeTransaction 必须在子线程中使用================///*realm.executeTransaction {it.insert(person)}*///========== 方式3:异步使用事务 ===================//realm.executeTransactionAsync({// 子线程中执行任务(copyToRealm 带返回值)// 注意这里不能用 realm 只能用 it,否则报错it.copyToRealm(person)// 必须设置主键id 且id不能相同,否则报错//  it.copyToRealmOrUpdate(person)// id相同则更新,否则插入}, {// 当前线程callback?.onResult(true, null, person)}) {// 当前线程callback?.onResult(false, it.message, null)}}/*** 删除数据*/fun deletePerson(id: Int, callback: RealmCallback?) {val realm = Realm.getDefaultInstance()//  realm.delete(PersonModel::class.java)// 全部删除realm.executeTransactionAsync({it.where(PersonModel::class.java).equalTo("id", id).findFirst()?.deleteFromRealm() ?: throw Throwable("User($id) doesn't exists",null)// 异常往外抛,统一在onResult线程中处理}, {callback?.onResult(true, null, null)}) {callback?.onResult(false, it.message, null)}}/*** 更新数据*/fun updatePerson(person: PersonModel, callback: RealmCallback?) {val realm = Realm.getDefaultInstance()realm.executeTransactionAsync({it.copyToRealmOrUpdate(person)}, {callback?.onResult(true, null, null)}) {callback?.onResult(false, it.message, null)}}/*** 查询数据:无需开启事务* realm 查询速度贼快(纯查询操作不放子线程也可)*/fun queryPerson(email: String): PersonModel? {val realm = Realm.getDefaultInstance()//  realm.where(PersonModel::class.java).findAll().forEach { DebugLog.d("$it") }// 查询指定邮箱且按id倒序的第一个PersonModelreturn realm.where(PersonModel::class.java).equalTo("email", email).sort("id", Sort.DESCENDING).findFirst()}@Synchronizedfun getNextId(): Long {return try {val realm = Realm.getDefaultInstance()val currentIdNum: Number? = realm.where(PersonModel::class.java).max("id")if (currentIdNum != null) currentIdNum.toLong() + 1 else 1L} catch (e: Exception) {val errorMsg = "Exception during getPrimaryKey(): " + e.messagethrow RealmPrimaryKeyConstraintException(errorMsg)}}}

3.4 RealmCallback DB操作回调

package com.hawky.hawkysdk.realm.realmdaoimport io.realm.RealmModelinterface RealmCallback {fun onResult(success: Boolean, error: String?, result: RealmModel?)
}

3.5 HawkyRealm DB配置初始化

package com.hawky.hawkysdk.realmimport android.content.Context
import io.realm.DynamicRealm
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.RealmMigrationobject HawkyRealm {private const val REALM_DATABASE_VERSION: Long = 1private const val REALM_DATABASE_NAME = "hawky.realm"/*** 初始化 Realm 参数配置*/fun init(context: Context) {Realm.init(context)val config = RealmConfiguration.Builder().name(REALM_DATABASE_NAME) // 设置库名,默认为 "default.realm".schemaVersion(REALM_DATABASE_VERSION) // 设置版本// 可指定初始化的数据库文件:// Realm会把assets路径下的xxx.realm文件拷贝到Context.getFilesDir()默认目录中,// 以替换默认创建的空数据库文件。// .assetFile("xxx.realm").migration(userMigration) // 升级.encryptionKey(getRealmKey())// 加密.build()// 设置config 为realm 默认配置,// 之后可通过 Realm.getDefaultInstance() 来创建或从缓存中拿到 Realm 对象。Realm.setDefaultConfiguration(config)// 当然也可以不进行 setDefaultConfiguration操作,// 通过 Realm.getInstance(config) 也可获取 Realm 对象。}/*** DB 升级使用*/private val userMigration =RealmMigration { realm: DynamicRealm, oldVersion: Long, newVersion: Long ->//...}/*** NOTE:Realm 密钥必须是64个字节,可自定义*/private fun getRealmKey() = byteArrayOf(0x03, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02,0x03, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02,0x03, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02,0x03, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02,0x03, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02,0x03, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02,0x03, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02,0x03, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03, 0x02)}

4)子模块 app

4.1 build.gradle

plugins {id 'com.android.application'id 'org.jetbrains.kotlin.android'id 'kotlin-kapt'id 'realm-android'
}android {// namespace:注意这个不是打包的包名,而是一些自动生成的类会引用到(import package)namespace 'com.hawky.realm'compileSdk rootProject.ext.compileSdkVersion// 配置签名signingConfigs {release {storeFile file('../keystore/hawky.jks')storePassword "hawky2023!"keyAlias "hawky"keyPassword "hawky2023!"}}defaultConfig {applicationId "com.hawky.realm"minSdk 24targetSdk 33multiDexEnabled trueflavorDimensions "brand"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}// 配置编译类型buildTypes {release {minifyEnabled true// release版本使用混淆buildConfigField "boolean", "IS_DEBUGENV", 'false'proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}debug {minifyEnabled false// debug版本不使用混淆buildConfigField "boolean", "IS_DEBUGENV", 'true'}// 对打包的 apk 重命名applicationVariants.all {variant ->variant.outputs.each {output ->def formattedDate = new Date().format('yyyyMMdd-HHmm')def newName = output.outputFile.namenewName = newName.replace("-release", "-release-" + formattedDate)newName = newName.replace("-debug", "-debug-" + formattedDate)output.outputFileName = newName}}}// 多渠道打包(applicationIdSuffix 改包名)// 若直接 build 打包,则会默认使用最后一个Flavor配置,apk生成路径:build/outputs/apk/huawei/// 若使用 签名 打包(如选择huawei),则apk生成路径 /app/huaweiproductFlavors {xiaomi {dimension "brand"applicationIdSuffix ".xiaomi"versionCode 1versionName "1.0"buildConfigField 'String', 'brand_id', '"xiaomi"'}huawei {dimension "brand"applicationIdSuffix ".huawei"versionCode 1versionName "1.0"buildConfigField "String", "brand_id", '"huawei"'}}compileOptions {sourceCompatibility JavaVersion.VERSION_17targetCompatibility JavaVersion.VERSION_17}/*lintOptions {abortOnError falsecheckReleaseBuilds true}*/kotlinOptions {jvmTarget = '17'}// 开启 dataBindingdataBinding {enabled = true}
}dependencies {implementation fileTree(dir: 'libs', include: ['*.jar'])implementation "androidx.core:core-ktx:$kotlin_version"implementation 'androidx.appcompat:appcompat:1.4.1'implementation 'com.google.android.material:material:1.5.0'implementation 'androidx.constraintlayout:constraintlayout:2.1.3'implementation 'com.android.support:multidex:1.0.3'implementation project(path: ':hawkybase')implementation project(path: ':hawkysdk-realm')testImplementation 'junit:junit:4.13.2'androidTestImplementation 'androidx.test.ext:junit:1.1.3'androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

4.2 RealmApplication

class RealmApplication : MultiDexApplication() {companion object {lateinit var instance: RealmApplicationprivate set}override fun onCreate() {super.onCreate()instance = this// init RealmDBHawkyRealm.init(this)}
}

4.3 User 实体类

class User : BaseObservable() {var id: Long = 0@Bindablevar name: String? = nullset(value) {field = valuenotifyPropertyChanged(BR._all)}@Bindablevar email: String? = nullset(value) {field = valuenotifyPropertyChanged(BR._all)}
}

4.4 MainActivity 测试类

package com.hawky.realm.uiimport android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.hawky.hawkybase.DebugLog
import com.hawky.hawkysdk.realm.realmdao.PersonDao
import com.hawky.hawkysdk.realm.realmdao.RealmCallback
import com.hawky.hawkysdk.realm.realmmodel.PersonModel
import com.hawky.realm.R
import com.hawky.realm.RealmApplication
import com.hawky.realm.databinding.ActivityMainBinding
import com.hawky.realm.model.User
import io.realm.RealmModelclass MainActivity : AppCompatActivity() {private lateinit var binding: ActivityMainBinding//private lateinit var realm: Realmoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)initView()initData()}private fun initView() {binding = DataBindingUtil.setContentView(this, R.layout.activity_main)}private fun initData() {// realm = Realm.getDefaultInstance()binding.event = HandleClickEvent()}// 处理点击事件inner class HandleClickEvent {fun addUser(view: View) {val person = PersonModel()person.id = PersonDao.getNextId()person.name = "张三"person.email = "123@qq.com"PersonDao.savePerson(person, object : RealmCallback {override fun onResult(success: Boolean, error: String?, result: RealmModel?) {if (success) {Toast.makeText(RealmApplication.instance, "ADD OK", Toast.LENGTH_SHORT).show()} else {Toast.makeText(RealmApplication.instance, error, Toast.LENGTH_SHORT).show()}}})}fun deleteUser(view: View) {PersonDao.deletePerson(0, object : RealmCallback {override fun onResult(success: Boolean, error: String?, result: RealmModel?) {if (success) {Toast.makeText(RealmApplication.instance, "DEL OK", Toast.LENGTH_SHORT).show()} else {Toast.makeText(RealmApplication.instance, error, Toast.LENGTH_SHORT).show()}}})}fun updateUser(view: View) {val person = PersonModel()person.id = 1person.name = "张三"person.email = "123456@qq.com"PersonDao.updatePerson(person, object : RealmCallback {override fun onResult(success: Boolean, error: String?, result: RealmModel?) {if (success) {Toast.makeText(RealmApplication.instance, "UPDATE OK", Toast.LENGTH_SHORT).show()person.run {val user = User()user.id = iduser.name = nameuser.email = emailbinding.user = user}} else {Toast.makeText(RealmApplication.instance, error, Toast.LENGTH_SHORT).show()}}})}fun queryUser(view: View) {val person = PersonDao.queryPerson("123@qq.com")DebugLog.d("person:${person}")person?.run {val user = User()user.id = iduser.name = nameuser.email = emailbinding.user = user}}}override fun onDestroy() {super.onDestroy()// 同一个Realm实例操作完成后,记得close()// realm.close()binding.unbind()}}

4.5 activity_main 布局文件

<layout xmlns:android="http://schemas.android.com/apk/res/android"><data><variablename="user"type="com.hawky.realm.model.User" /><variablename="event"type="com.hawky.realm.ui.MainActivity.HandleClickEvent" /></data><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/btn_add"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginTop="20dp"android:onClick="@{event::addUser}"android:text="添加数据" /><Buttonandroid:id="@+id/btn_delete"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginTop="20dp"android:onClick="@{event::deleteUser}"android:text="删除数据" /><Buttonandroid:id="@+id/btn_modify"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginTop="20dp"android:onClick="@{event::updateUser}"android:text="修改数据" /><Buttonandroid:id="@+id/btn_query"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginTop="20dp"android:onClick="@{event::queryUser}"android:text="查询数据" /><TextViewandroid:layout_width="match_parent"android:layout_height="40dp"android:layout_gravity="center"android:layout_marginTop="20dp"android:background="#BBBBBB"android:gravity="center"android:text="@{@string/nameFormat(user.id,user.name,user.email)}" /></LinearLayout>
</layout>

字符引用:<string name="nameFormat">%s---%s---%s</string>

小结

通过本文,相信大家对 Gradle 8.0 的配置说明 及 Realm 数据库实例操作有了一定了解。后面计划:1. 添加Realm 数据迁移实例内容。2.以task生成aar的形式,加快编译速度。

最后,代码已上传至GitHub:hawky-kotlin-realm。

AS Gradle 8.0 配置 + Realm 使用相关推荐

  1. android studio gradle home,Android Studio3.0 Gradle 4.1配置

    Android Studio 3.0正式发行, 安装后可以跟2.3.3一起存在.安装后,构建project时出现gradle4.1找不到错误. 原因: setting下gradle下设置gradle选 ...

  2. 【Android Gradle 插件】gradle.properties 中配置编译参数并在 Java 代码 BuildConfig 中调用该参数

    文章目录 一.gradle.properties 中配置编译参数 二.在 build.gradle 中配置 BuildConfig.java 生成信息 三.编译后生成的 BuildConfig 类 A ...

  3. 【AOP 面向切面编程】Android Studio 中配置 AspectJ ( 下载并配置AS中 jar 包 | 配置 Gradle 和 Gradle 插件版本 | 配置 Gradle 构建脚本 )

    文章目录 一.AspectJ 下载 二.拷贝 aspectjrt.jar 到 Android Studio 三.配置 Gradle 和 Gradle 插件版本 四.配置 Gradle 构建脚本 一.A ...

  4. 史上最快、最强大的Gradle 5.0发布,新特性全解

    Gradle 5.0是有史以来速度最快.最安全.最强大的Gradle版本,这是Gradle官方给出的评价,v5.0 新增的功能主要包括: 在构建缓存和更新检查功能的基础之上,Gradle 5.0又改进 ...

  5. Android 使用 Gradle 打包 - 签名配置

    序言 最近正好在项目里用到了 Gradle 打包的配置,顺便总结一下. 一般的 apk 打包类型分为 debug 和 release:debug 开启日志,不进行混淆,用于测试:release 关闭日 ...

  6. Android Studio Arctic Fox | 2020.3.1、Gradle 7.0升级记录

    环境 Android Studio Arctic Fox | 2020.3.1 Gradle.AGP 7.0 Kotlin 1.5.31 问题1 Value '/Applications/Androi ...

  7. gradle linux配置环境变量配置文件,gradle init.gradle的文件配置 使用

    init.gradle文件在build开始之前执行,所以你可以在这个文件配置一些你想预先加载的操作 例如配置build日志输出.配置你的机器信息,比如jdk安装目录,配置在build时必须个人信息,比 ...

  8. android gradle 版本部队,gradle中统一配置版本的小技巧。

    在Project/build.gradle中定义,在module/build.gradle中使用 1.直接在Project/build.gradle中定义和引用: // Top-level build ...

  9. Gradle 2.0 用户指南翻译——第五十一章. 发布工件

    本文禁止w3cschool转载! 翻译项目请关注Github上的地址:https://github.com/msdx/gradledoc . 本文翻译所在分支:https://github.com/m ...

最新文章

  1. 英语音标 [j] yes
  2. 管理Vim插件的插件——Vundle
  3. mysql backlog_一次优化引发的血案
  4. datagrid如何获取一行数据中的某个字段值_使用Mysql 数据库 新手常见问题
  5. Network device support
  6. Python:利用python语言绘制多个子图经典案例、代码实现之详细攻略
  7. elon函数_Neuroink Elon麝香制造中的灾难
  8. python泰坦尼克号数据预测_机器学习入门之Python机器学习:泰坦尼克号获救预测一...
  9. Scratch3 二次开发系列
  10. 如果你需要万圣节的图片素材来点缀你的节日活动,看这里就对了
  11. 期货市场技术分析01_理论基础
  12. Learning to Refine Object Segments
  13. Java 创建线程的三种方法比较
  14. a标签href不跳转 禁止跳转
  15. tshark过滤并保存包特定字段
  16. 【Qt开发】关于QWSServer
  17. python金融数据分析与挖掘实战_[套装书]Python数据分析与挖掘实战(第2版)+Python金融大数据挖掘与分析全流程详解+Python金融数据分析(3册)...
  18. 【零基础】计算机网络技术基础与就业前景
  19. matlab中readfid函数,matlab中textscan和textread函数的比较使用
  20. ABeam中国2022社招 | ABeam旗下艾宾信息技术开发(大连) 最新招聘信息

热门文章

  1. 游戏配音教程分享给你
  2. Revit二次开发-【NO.05】获取元素的三种方法
  3. Nova — 启动 GPU Passthrough 虚拟机(Nova Centric 模式)
  4. 【Windows】Win10家庭版启用组策略gpedit.msc
  5. Xcode中系统库文件libz.dylib的作用
  6. 快手资讯|打不倒的辛巴强势复出!回归首秀GMV近20亿
  7. uniapp中背景颜色使用scss变量不生效
  8. 三、寄存器-计算机基础
  9. 4D毫米波雷达算法设计1--必要性与可行性
  10. python panda 库 累积分布,Python Pandas:使用滚动回溯窗口计算累计总和