目录
Android 从0搭建初始化MVVM项目框架(二):添加版本依赖管理、数据库、路由、分包分模块、组件化Aroute
一、添加依赖版本管理
为什么需要依赖版本管理?以前我们可能是这样写的:
dependencies {
implementation "org.greenrobot:eventbus:3.2.0"
implementation "com.squareup.okhttp3:okhttp:4.9.0"// OkHttp
implementation "com.squareup.okhttp3:logging-interceptor:4.9.1"// OkHttp 请求Log拦截器
implementation "com.squareup.retrofit2:retrofit:2.9.0"// Retrofit
implementation "com.squareup.retrofit2:converter-gson:2.9.0"// Retrofit Gson 转换器
implementation "com.squareup.retrofit2:converter-scalars:2.9.0" // Retrofit String 转换器
implementation "com.google.dagger:hilt-android:2.44"// DI框架-Hilt
kapt "com.google.dagger:hilt-compiler:2.44"// DI框架-Hilt
implementation "androidx.room:room-runtime:2.6.0"
kapt "androidx.room:room-compiler:2.6.0"
implementation "androidx.room:room-ktx:2.6.0"
}
这是传统的依赖管理,如果版本号变化,就需要全部改动,如果其他模块需要增加,也得复制过去,存在出错的可能性,以及维护复杂。接下来我们会介绍几种依赖版本管理的方式,分别有:config.gradle、buildSrc以及Version Catalogs。
1.1 config.gradle
● 优点:更新只需修改 config.gradle 文件内容,作用于所有module。
● 缺点:缺乏Android Studio的支持,不能自动补全和链接跳转。
● 使用场景:适用于需要集中管理依赖但不需要IDE支持的项目。
● 使用方法:新建一个 config.gradle 文件,然后将项目中所有依赖写在里面。
ext {
android = [
"compileSdkVersion" : 30,
"minSdkVersion" : 19,
"targetSdkVersion" : 28,
"versionCode" : 1,
"versionName" : "1.0.0",
"androidSupport" : "28.0.0",
"constraint-layout" : "1.1.3",
"junit" : '4.12',
"runner" : '1.0.2'
]
dependencies = [
"appcompat-v7" : "com.android.support:appcompat-v7:${android["androidSupport"]}",
"constraint-layout" : "com.android.support.constraint:constraint-layout:${android["constraint-layout"]}",
"junit" : "junit:junit:${android["junit"]}"
]
}
在项目的build.gradle里面引入即可。
//项目 build.gradle
apply from: "config.gradle"
//app build.gradle
dependencies {
// 添加appcompat-v7依赖
implementation rootProject.ext.dependencies["appcompat-v7"]
}
1.2、buildSrc(本项目使用)
● 优点:更好的组织和共享依赖,减少了 build.gradle 文件的复杂性。
● 缺点:需要创建额外的 buildSrc 子项目。
● 使用场景:适用于中等规模的项目,需要更好的组织和共享依赖的情况。
● 使用方法:创建一个名为 buildSrc 的子项目,在其中创建一个Kotlin文件定义依赖项,然后在主项目的 build.gradle 中使用这些依赖项。
步骤
● 创建 buildSrc 目录: 在项目根目录下新建一个名为 buildSrc 的文件夹(与项目里的 app 文件夹同级)。
● 配置 buildSrc 的 build.gradle.kts 文件: 在 buildSrc 文件夹里创建名为 build.gradle.kts 的文件,用于配置 buildSrc 的构建脚本。例如:
plugins {
`kotlin-dsl` }
repositories {
mavenCentral() }
● 创建依赖定义文件: 在 buildSrc 文件夹里创建 src/main/kotlin, 并在该文件夹下创建一个Kotlin文件,例如 Dependencies.kt,用于定义依赖项。
object Dependencies {
object Version {
const val OkHttp = "4.9.0" // OkHttp
}
object GitHub {
const val OkHttp = "com.squareup.okhttp3:okhttp:${
Version.OkHttp}"
}
}
● 使用 buildSrc 中的依赖: 在其他模块的 build.gradle 文件中,你可以通过以下方式使用 buildSrc 中定义的依赖项:
//全部引入buildsrc的
import com.zwl.buildsrc.*
//或者
import com.zwl.buildsrc.Dependencies
dependencies {
api Dependencies.Github.OkHttp
}
● 同步项目: 执行一次 Gradle Sync 任务,现在你可以在Android Studio中访问 Dependencies.kt 中任何值了。
● 重启Android Studio: 构建一遍你的项目,然后重启你的Android Studio,项目里就会多出一个名为 buildSrc 的module。
1.3 Version Catalogs:
现在你默认创建一个项目,使用的就是Version Catalogs的方式。
● 优点:集中管理依赖版本,减少版本冲突,可以轻松共享版本信息到多个项目中。
● 缺点:需要学习和使用 .toml 文件格式,要求Gradle版本在7.4.2以上。
● 适用场景:适用于大型团队合作的复杂项目,需要更严格的版本管理和共享版本信息的情况。
使用方式:在项目的根目录下创建一个名为 dependencies.toml 的 .toml 文件,定义依赖项。然后在主项目的 settings.gradle.kts 文件中,指定Version Catalogs的位置。
[versions]
agp = "8.6.0"
kotlin = "1.8.0"
coreKtx = "1.10.1"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
appcompat = "1.6.1"
material = "1.10.0"
activity = "1.8.0"
constraintlayout = "2.1.4"
hilt = "2.44"
[libraries]
androidx-core-ktx = {
group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = {
group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = {
group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = {
group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-appcompat = {
group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = {
group = "com.google.android.material", name = "material", version.ref = "material" }
androidx-activity = {
group = "androidx.activity", name = "activity", version.ref = "activity" }
androidx-constraintlayout = {
group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
[plugins]
android-application = {
id = "com.android.application", version.ref = "agp" }
kotlin-android = {
id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
hilt = {
id = "com.google.dagger.hilt.android", version.ref = "hilt" }
进行使用
import com.zwl.buildsrc.*
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.hilt)
id "kotlin-kapt"
}
android {
namespace 'com.example.android_init'
compileSdk 34
defaultConfig {
applicationId "com.example.android_init"
minSdk 24
targetSdk 34
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
viewBinding {
enabled = true
}
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
//排除debug文件夹下的所有文件
exclude 'debug/**'
}
}
}
// 第三方本地库引入所需
packagingOptions {
exclude 'META-INF/gradle/incremental.annotation.processors'
exclude 'META-INF/library_release.kotlin_module'
}
}
dependencies {
implementation libs.androidx.core.ktx
implementation libs.androidx.appcompat
implementation libs.material
implementation libs.androidx.activity
implementation libs.androidx.constraintlayout
testImplementation libs.junit
androidTestImplementation libs.androidx.junit
androidTestImplementation libs.androidx.espresso.core
implementation DependencyConfig.GitHub.EventBus
implementation DependencyConfig.GitHub.EventBusAPT
implementation DependencyConfig.GitHub.OkHttp
implementation DependencyConfig.GitHub.OkHttpInterceptorLogging
implementation DependencyConfig.GitHub.Retrofit
implementation DependencyConfig.GitHub.RetrofitConverterGson
implementation DependencyConfig.GitHub.RetrofitConverterScalars
implementation DependencyConfig.JetPack.HiltCore
implementation DependencyConfig.JetPack.HiltAp
}
二、分包分模块,如何分?为什么要分?
为什么需要分包分模块呢?
一方面是因为开发者可以并行开发不同的模块,从而提高开发效率。这有助于缩短应用程序的开发周期,并快速响应市场需求。
一方面是因为开发者可以更加清晰地组织代码,每个模块负责特定的功能或业务逻辑。这有助于提升代码的可读性和可维护性,使得团队协作更加高效。
创建多个模块
前面,我们只有一个app模块,现在我们增加一个module_chat和module_map模块,也就是聊天和地图模块,开发聊天的伙伴可以开发他的,开发地图模块的兄弟开发他的,互不干扰,独立运行。
那么模块多了以后,肯定会有很多相同的依赖呀、相同的util等等,所以,我们需要创建一个lib模块(lib_common),专门用于抽取共同项。
好的,到这里就大功告成了,但是,我们如何将新增的模块整合成一个app呢?现在他们还是独立运行的,接下面我们就需要使用组件化框架Aroute。
三、整合Aroute
添加路由依赖
const val ARoute = "1.5.2" // 阿里路由
const val ARouteCompiler = "1.5.2" // 阿里路由 APT
const val ARoute = "com.alibaba:arouter-api:${
Version.ARoute}"
const val ARouteCompiler = "com.alibaba:arouter-compiler:${
Version.ARouteCompiler}"
kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.getName())
}
}
在Application中进行初始化
if (BuildConfig.VERSION_TYPE != VersionStatus.RELEASE) {
ARouter.openLog() // 打印日志
ARouter.openDebug() // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
}
ARouter.init(this@AppApplication)
然后我们需要创建一个参数,用于决定是否开启组件化,如果开启则整合到一起,如果关闭则可以单独运行。
/**
* app相关参数配置
*/
object AppBuildParamConfig {
const val isAppMode = false //组件化
}
分别在module_chat和module_map模块里面添加
if (ProjectBuildConfig.isAppMode) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
那么模块组件如何通讯跳转呢?如下这样,我们先创建一个路由字符串
object RouteUrl {
/**
* 后台模块
*/
object Background {
/**
* 后台模块MainActivity2
*/
const val MainActivity2 = "/module_background/MainActivity2"
}
}
//module_chat
@Route(path = RouteUrl.Background.MainActivity2)
class MainActivity2 : AppCompatActivity() {
}
然后我们在module_map跳转到module_chat的Activity
override fun init() {
dataBinding.tvTitle.setOnClickListener {
ARouter.getInstance().build(RouteUrl.Background.MainActivity2).navigation()
}
}
这篇文章就介绍到这里~