一、什么是SDK
SDK,全称为Software Development Kit,即软件开发工具包。可以简单的理解为别人写好的代码包,造好的轮子,我们可以直接拿过来用,以Android开发为例,我们在gradle的dependencies {}中引入(implementation)的各种依赖本质上就是SDK,例如Retrofit、OkHttp等。
二、什么是依赖?为什么要有依赖?
1.是什么:
依赖,简而言之就是把别人造好的"轮子"直接拿来用。
2.为什么:
依赖的核心价值是复用成熟代码、避免重复造轮子,大幅提升开发效率和代码稳定性。
我们可以把开发应用类比成 "组装一台电脑":
-
你不需要自己造 CPU、内存条、硬盘(这些是 "现成的组件"),只需要采购这些组件,然后组装成完整的电脑;
-
这里的 "CPU / 内存条" 就是开发中的依赖库 ,"采购并组装" 就是引入依赖的过程。
如果没有依赖,你需要从零造 CPU(写底层代码)、造内存条(写存储逻辑)------ 这既不现实,也完全没必要。
三、Android中依赖的种类及适用场景
我们要把别人造好的"轮子"直接拿来用,需要两个步骤:
1、拿到"轮子"(得知源代码在哪里,依赖来源)
仓库:远程仓库、本地仓库
项目依赖模块:本项目的依赖模块
编译打包文件:编译打包为jar、aar包的源代码
2、用(在项目中的gradle文件中配置依赖)
1.远程仓库依赖
(1)定义:
直接在当前项目中,通过「Maven 坐标(groupId:artifactId:version)」的形式,从远程的仓库服务器 上拉取依赖库文件,无需在本地存放任何库文件(首次拉取后会缓存到本地.m2目录,后续无需重复下载),是 Android 开发中最主流、使用频率最高的依赖方式。
(2)核心特点:
-
完全遵循 Maven 规范,依赖的核心是「坐标」而非「文件」,所有依赖的管理都通过坐标实现;
-
版本管理最规范、最完善:支持指定版本、最新版本、快照版本(SNAPSHOT)、稳定版本,可通过版本号锁定依赖,避免版本漂移;
-
天然支持自动依赖传递:远程仓库的依赖库都带有 pom.xml 文件,Gradle 会自动解析并拉取所有子依赖,无需手动处理;
-
依赖的是编译产物,默认无源码,但几乎所有主流开源库都提供了源码包,引入后即可调试;
-
首次拉取需要联网,后续会缓存到本地,再次使用无需联网;
-
依赖库存放在远程服务器,所有有权限的人 / 项目都能引用,是团队协作的最优解。
(3)配置方式:
① 在根目录settings.gradle中配置对应的远程仓库(全局生效,只需配置一次):
Groovy
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google() // 谷歌官方仓库(必配)
mavenCentral() // Maven中央仓库(必配)
// 可选:公司私有仓库(需要账号密码)
// maven {
// url = uri("https://xxx.xxx.com/repository/maven-public/")
// credentials {
// username = "账号"
// password = "密码"
// }
// }
}
}
② 在app/build.gradle中通过坐标引入依赖:
Groovy
dependencies {
// 开源库示例:Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
// 公司自研库示例(私服)
implementation 'com.xxx.enterprise:base-lib:2.3.1'
}
适用场景:
-
引入所有开源第三方库(Retrofit、OkHttp、Glide、Room、协程等);
-
企业 / 团队多人协作开发 ,需要共享自研的组件库、业务库 ,保证所有人使用的依赖版本一致;
-
自研库已经定稿、测试完成,需要长期稳定提供给多个项目、多个团队使用;
-
项目需要跨电脑、跨环境使用,无需复制任何文件,只需配置坐标即可;
-
追求最简洁的依赖管理方式,最低的维护成本和协作成本。
2.本地发布依赖
(1)定义:
将其他 Android 项目(Library Module),通过 Gradle 的maven-publish插件,打包成符合完整 Maven 规范的库文件 (包含 AAR 包、pom.xml 依赖清单、源码包、javadoc 文档包),发布到电脑本地的 Maven 仓库 中(默认路径:C:\用户\你的用户名\.m2\repository,也可自定义本地目录),然后在当前项目中通过「Maven 坐标(groupId:artifactId:version)」的形式引入依赖。
(2)核心特点:
-
本质是「本地的依赖 」:完全遵循 Maven 规范,和远程依赖的使用方式、语法一模一样,可以理解为服务器为本地电脑,源代码文件存放在本地电脑,而非远程服务器;
-
有明确的版本号:发布时必须指定版本号(如 1.0.0、1.1.0-beta),版本管理清晰,可按需引入指定版本,更新时只需要修改版本号即可,无需复制任何文件;
-
天然支持自动依赖传递:pom.xml 文件中会自动记录被依赖库的所有子依赖(比如自研库依赖 Retrofit+Gson),主项目引入时会自动拉取这些子依赖,无需手动配置,完美解决打包依赖的痛点;
-
依赖的是编译后的产物,默认无源码,如需调试源码,发布时可配置打包源码包,引入后即可断点调试;
-
纯本地依赖,无需联网,只要发布到本地仓库,任何本地项目都能引用,无需复制文件。
(3)配置方式:
步骤 1:在被依赖的 Library 模块(如 network)的build.gradle中配置发布脚本
Groovy
plugins {
id 'com.android.library'
id 'maven-publish' // 引入maven发布插件(核心)
}
android {
compileSdk 34
defaultConfig {
minSdk 21
targetSdk 34
versionCode 1
versionName "1.0.0"
// 配置Maven坐标的核心三要素(必配)
group = "com.xxx.project" // 包名,一般用公司/项目域名
version = "1.0.0" // 版本号
archivesBaseName = "network" // artifactId,模块名/库名
}
}
// 可选:打包源码包(发布后,主项目引入可直接调试源码,推荐配置)
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
// 发布核心配置
afterEvaluate {
publishing {
publications {
release(MavenPublication) {
from components.release // 发布release版本的AAR包
artifact sourcesJar // 附带源码包
}
}
repositories {
mavenLocal() // 发布到【默认本地Maven仓库】.m2目录
// 可选:发布到自定义本地目录,比如项目根目录下的local-maven
// maven {
// url = uri("$rootDir/../local-maven")
// }
}
}
}
步骤 2:执行发布命令
在 Android Studio 右侧的「Gradle」面板,找到该 Library 模块 → 点击「publishing」→ 双击执行「publishToMavenLocal」,执行成功即发布完成。
步骤 3:当前项目引入依赖
① 在根目录settings.gradle中配置本地 Maven 仓库:
Groovy
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
mavenLocal() // 引入本地Maven仓库(核心),若自定义了本地Maven仓库的位置,此处就需修改为你自定义的位置了
}
}
② 在app/build.gradle中通过坐标引入:
Groovy
dependencies {
// 和远程依赖写法完全一致!
implementation 'com.xxx.project:network:1.0.0'
}
(4)适用场景:
-
自己电脑上有多个独立的 Android 项目,需要复用同一个自研库(比如 base 库、网络库),不想复制 Module/Jar/AAR,减少重复维护成本;
-
自研库有版本迭代需求,需要清晰的版本号管理,避免版本混乱;
-
自研库有多层依赖 关系,想自动处理依赖传递,不想手动引入子依赖;
-
无网络环境开发,无法使用远程仓库,但又想享受 Maven 规范的版本和依赖传递优势;
-
自研库还在迭代测试阶段,暂不适合发布到远程 私服 / 公共仓库,先在本地验证使用。
(5)小故事理解:为什么要做「本地发布」?
主要是为了解决 「模块依赖跨项目复用不了」 + 「打包依赖无版本 / 无依赖传递」 的痛点。
它是连接 「本地依赖」 (方便调试但难以管理)到**「远程依赖」** (规范但流程繁琐)的最佳过渡方案。
紧急修复!自研 SDK Bug 拦截上线,本地发布救场记
A 公司的 Android 团队一直遵循着一套高效的开发模式:所有通用能力(如网络、埋点、UI 组件)都封装成自研 SDK,发布到公司内部的 Maven 私服。各业务线(电商 App、办公 App 等)只需通过一行远程依赖代码即可引入,既保证了版本统一,又避免了重复造轮子。
危机突现
这天,电商 App 项目组的核心开发小明正盯着上线前的最后一轮测试。突然,测试同学发来一条紧急消息:"支付页面偶现崩溃,日志指向自研网络 SDK com.a.company:network-sdk:2.3.0。"
距离计划上线仅剩 6 小时,支付模块是核心中的核心,绝不能出问题!
定位与修复
小明迅速拉取日志,很快定位到了问题:SDK 在处理弱网环境下的空响应时,未做非空判断,导致抛出空指针异常。
这个 Bug 修复起来很简单,只需加一行判空代码。但麻烦的是,该 SDK 由架构组维护,发布到公司私服必须走严格的审批流程(提交评审 → 架构组验证 → 版本升级 → 私服发布),这一圈跑下来至少需要 2 天,根本赶不上今晚的上线窗口。
破局:本地发布登场
"总不能因为一个小 Bug 耽误整个版本上线吧?"
小明决定另辟蹊径。他拉取了 SDK 的源码,切换到对应分支,迅速修复了 Bug 并通过了单元测试。
此时,他面临两个选择:
-
打包 AAR 引入?不行,电商 App 有 3 个业务模块都依赖了这个 SDK,逐个复制 AAR 不仅繁琐,还无法处理依赖传递。
-
使用本地发布!对,就是它。既不需要走公司审批流程,又能享受 Maven 依赖的所有便利。
实操落地
-
发布到本地 :小明在 SDK 项目的
build.gradle中配置好发布脚本,将版本号定为2.3.0-fix(加后缀以示区别),然后执行publishToMavenLocal任务。不到 1 分钟,修复后的 SDK 就躺在了他电脑的.m2仓库里。 -
调整项目依赖
-
在电商 App 的
settings.gradle中,小明特意将mavenLocal()的声明顺序放在了公司私服之前,确保 Gradle 优先拉取本地版本。 -
将
build.gradle中的依赖坐标修改为:implementation 'com.a.company:network-sdk:2.3.0-fix'。
-
化险为夷
点击同步,项目顺利构建成功。经过全面回归测试,支付页面的崩溃问题彻底消失,其他功能也一切正常。
当晚,电商 App 按时上线,用户支付流程平稳运行。小明长舒一口气,随后将修复代码提交给架构组进行评审,准备在后续版本中切回官方发布的正式版。
故事启示
这个小插曲证明了:本地发布依赖 不是 "非主流操作",而是紧急修复场景下的 "救命稻草"。
它完美平衡了 "规范" 与 "效率" ------ 既保留了远程依赖的坐标管理和依赖传递特性,又避开了冗长的官方发布流程,让开发者能快速验证修复效果,保障业务按时上线。
3.打包依赖
(1)定义:
将其他项目进行编译打包 变成Jar 包 / AAR 包 文件,直接复制到当前项目的指定目录(默认app/libs),以「本地文件」的形式引入依赖,完全无 Maven 规范约束,也不需要任何仓库支持,是最纯粹的本地文件引用。
补充:Jar 包 和 AAR 包 的区别
Jar 包 :Java 的标准打包格式,仅包含Java 字节码文件,无任何 Android 相关资源,不能包含布局 xml、图片、drawable、AndroidManifest 清单文件、自定义属性等 Android 专属内容,适合纯 Java 工具类库(如 Gson 核心包、Okio)。
AAR 包 :Android 专属的打包格式,是 Android Library 的编译产物,全能型格式 ,包含 Java 字节码 + Android 所有资源(布局、图片、颜色、样式、清单文件、so 库等),是 Android 本地打包依赖的主流形式,99% 的 Android 本地文件依赖都是用 AAR 包。
(2)核心特点:
-
依赖的是编译后的产物文件,不是源码,默认情况下看不到源码、无法直接调试(除非额外导入对应的源码文件);如果要修改依赖库的逻辑,必须回到原项目修改后重新打包成 Jar/AAR,再替换当前项目的文件。
-
无版本概念,没有版本号,更新依赖的唯一方式就是「删除旧文件、复制新文件」,版本管理完全靠人工维护,极易出现版本混乱(比如分不清当前用的是 1.0 还是 2.0 版本)。
-
不支持依赖传递 :这是最大的痛点!如果这个 Jar/AAR 包本身依赖了其他库(比如 AAR 包依赖 Retrofit),主项目必须手动在
dependencies中重复引入这些依赖,否则会报ClassNotFound类找不到异常。 -
纯本地依赖,无需联网、无需配置仓库,只要文件存在就能引入。
(3)配置方式:
Jar 包依赖(直接引入)
将 Jar 包复制到app/libs目录,直接在build.gradle中引用即可:
Groovy
dependencies {
// 单个Jar包依赖
implementation files('libs/okio-3.4.0.jar')
// 批量引入libs目录下所有Jar包(推荐)
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
AAR 包依赖(需声明本地仓库,必配)
将 AAR 包复制到app/libs目录,AAR 依赖需要先声明「本地扁平仓库」,再引入,缺一不可:
Groovy
android {
compileSdk 34
// 其他配置...
}
// 声明本地libs目录为扁平仓库(AAR依赖必须配置)
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
// 引入AAR包:只写文件名,不要带 .aar 后缀!
implementation(name: 'network-release', ext: 'aar')
}
(4)适用场景:
-
临时使用 某个第三方库 / 自研库,不想配置复杂的发布流程,快速集成到项目中;
-
被依赖的库已经定稿,后续 几乎不需要修改 ,无需调试源码;
-
无网络 环境开发,无法拉取远程仓库,也无法发布本地 Maven;
-
小体量的工具类库,无多层依赖关系(避免手动处理依赖传递的麻烦)。
4.模块依赖:
(1)定义:
模块依赖的形态主要有两种,但核心载体都是 Android 中的 Android Library 类型的 Module (库模块),最终都是在主模块:app中通过 implementation project(':xxx') 语法引入,这是所有形态的统一基础。
①【源码导入依赖】- 导入其他项目的完整源码作为本地依赖模块(跨项目复用源码):
将另一个独立 Android 项目的完整源码工程 ,直接导入到当前项目中 ,作为当前项目的一个Library模块,主模块:app依赖这个导入的源码模块。本质是:把别人的完整项目,变成自己项目的一个子模块,依赖的是「完整的源码」。
②【包体托管模块】- 创建独立模块,专门存放 Jar/AAR 包做「统一依赖托管」(最实用的进阶方案,大型项目必用):
专门创建一个空的 / 轻量化的 Library 模块 (比如命名为:libs、:repository、:thirdlib),这个模块的唯一作用就是:统一存放项目中所有的本地 Jar 包、AAR 包 ,然后在这个模块中引入这些 Jar/AAR 包,最后主模块:app只需要依赖这个「包体托管模块」即可。
(2)项目源码直接导入为依赖模块(不常用)
①核心特征
-
依赖的是其他项目的完整源码,导入后该源码会成为当前项目的一个 Module,源码完全可见、可修改、可断点调试;
-
导入的模块是「独立项目的源码」,和当前项目是两个不同的工程,只是物理上合并到了一个根目录下;
-
支持修改源码:这是该方式的核心价值,如果需要对依赖的库做定制化开发,这是最优解;
-
无版本概念,修改导入模块的源码,会直接影响当前项目的使用效果。
②配置方式
步骤 1:导入其他项目的源码到当前工程
① Android Studio 顶部菜单栏 → File → New → Import Module;
② 在弹窗中选择「其他项目的根目录」(比如D:\AndroidProject\BaseLib);
③ 自定义模块名称(比如base_lib),点击Finish,AS 会自动将该项目的源码导入为当前工程的一个 Library Module;
步骤 2:声明依赖(和原生模块完全一致)
Groovy
// 1. settings.gradle 中会自动新增导入的模块声明
include ':app', ':base_lib'
// 2. app/build.gradle 中引入依赖
dependencies {
implementation project(':base_lib')
}
(3)包体托管依赖模块(常用)
①核心特征
-
托管模块(如
:libs)是纯依赖容器,自身几乎无业务代码,只存放 Jar/AAR 文件 + 依赖配置; -
所有本地的 Jar/AAR 包,只需要放入该模块的
libs目录一次 ,所有其他模块(:app、:module_order等)都可以通过依赖该模块间接使用这些包; -
主模块和其他业务模块,无需再配置
flatDir仓库、无需再写files/name:ext语法,只需要写一行模块依赖即可,配置极度简洁; -
依赖的是编译后的 Jar/AAR 产物,无源码(需手动导入源码),无法直接修改包内逻辑;
-
天然支持全局依赖统一:修改托管模块中的 Jar/AAR 版本,所有依赖该模块的子模块都会同步更新,无需逐个修改。
②配置方式
步骤 1:创建「依赖模块」
Android Studio → File → New → New Module → 选择「Android Library」→ 命名为:libs(可自定义)→ 完成创建。
步骤 2:存放 Jar/AAR 包
将所有的 Jar 包、AAR 包,复制到:libs模块下的libs目录中(无则新建),比如:wxpay.aar、alipay.aar、gaode_map.jar。
步骤 3:配置:libs模块的build.gradle(核心)
Groovy
plugins {
id 'com.android.library'
}
android {
compileSdk 34
defaultConfig {
minSdk 21
targetSdk 34
}
}
// 声明本地flatDir仓库(AAR包必须配置,只在该模块配置一次即可)
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
// 1. 引入当前模块libs目录下的所有Jar包
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 2. 引入当前模块libs目录下的所有AAR包(逐个声明,无其他写法)
implementation(name: 'wxpay-release', ext: 'aar')
implementation(name: 'alipay-release', ext: 'aar')
implementation(name: 'gaode-map-release', ext: 'aar')
//可选
// 同时进行远程依赖统一声明
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.bumptech.glide:glide:4.16.0'
implementation 'com.google.code.gson:gson:2.10.1'
}
步骤 4:主模块:app依赖托管模块(一行代码搞定,核心简化)
Groovy
// app/build.gradle
dependencies {
// 只需依赖托管模块,即可直接使用里面所有的Jar/AAR包
implementation project(':libs')
// 其他业务模块依赖
implementation project(':base')
}