面试题答案
一键面试1. 在Kotlin多模块项目中使用Gradle进行模块间依赖管理
- 在settings.gradle文件中配置模块
在项目根目录下的
settings.gradle
文件中,声明项目包含的模块。例如:
这里include ':app', ':module1', ':module2'
:app
通常是主应用模块,:module1
和:module2
是自定义的其他模块。 - 在模块的build.gradle文件中添加依赖
假设
:module1
依赖:module2
,在:module1
的build.gradle.kts
(Kotlin DSL)文件中添加如下依赖:
或者在dependencies { implementation(project(":module2")) }
build.gradle
(Groovy DSL)文件中:dependencies { implementation project(':module2') }
2. 不同类型依赖的使用场景及区别
- implementation
- 使用场景:当一个模块内部使用另一个模块,但不希望将该依赖暴露给使用此模块的其他模块时使用。例如,
:module1
内部使用:module2
来实现一些内部逻辑,而:module1
对外提供的API并不依赖:module2
的具体实现。 - 优点:减少传递性依赖,降低模块之间的耦合度。如果
:module2
的API发生变化,只要:module1
的API不变,依赖:module1
的其他模块不会受到影响。
- 使用场景:当一个模块内部使用另一个模块,但不希望将该依赖暴露给使用此模块的其他模块时使用。例如,
- api
- 使用场景:当一个模块不仅自己使用另一个模块,而且希望将该依赖暴露给使用此模块的其他模块时使用。比如,
:module1
是一个基础库模块,它依赖:module2
的某些功能,而使用:module1
的其他模块可能也需要直接使用:module2
的功能。 - 缺点:增加了传递性依赖,可能导致依赖冲突。如果多个模块通过
api
依赖同一个模块的不同版本,可能会出现编译或运行时错误。
- 使用场景:当一个模块不仅自己使用另一个模块,而且希望将该依赖暴露给使用此模块的其他模块时使用。比如,
- runtimeOnly
- 使用场景:表示该依赖仅在运行时需要,编译时不需要。例如,某个模块依赖一个运行时的日志库,在编译阶段代码中并不直接引用该库的API,只是在运行时才会使用到。
- testImplementation
- 使用场景:专门用于测试相关的依赖。比如,JUnit、Mockito等测试框架,只在模块的测试代码中使用,不会影响主代码的依赖。
- androidTestImplementation
- 使用场景:用于Android应用模块的Instrumented测试(在设备或模拟器上运行的测试)。例如,Espresso等用于UI测试的库,只在Android应用的Instrumented测试代码中使用。