如何用Dagger 2在Kotlin Android应用中实现依赖注入:基于PhotoAffix的完整教程

📅 2026/8/26 15:57:53
如何用Dagger 2在Kotlin Android应用中实现依赖注入:基于PhotoAffix的完整教程
如何用Dagger 2在Kotlin Android应用中实现依赖注入基于PhotoAffix的完整教程【免费下载链接】photo-affix Stitch your photos together vertically or horizontally easily!项目地址: https://gitcode.com/gh_mirrors/ph/photo-affixPhotoAffix 是一款用 Kotlin 编写的 Android 照片拼接应用它将 Dagger 2 依赖注入框架运用得恰到好处通过 1 个 AppComponent 和 5 个 Module把图片引擎、用户偏好、协程调度器等依赖自动装配到界面层。这篇完整教程带你从核心概念到实战源码快速掌握 Dagger 2 依赖注入的全部用法。PhotoAffix 是什么轻量级照片拼接 Android 应用 PhotoAffix 的玩法很简单导入手机里的照片选择横向或纵向排列调整尺寸与间距一键拼接成一张大图导出。它采用多模块multi-module架构将界面、引擎、偏好、工具拆分为独立子项目而这正是引入Dagger 2 依赖注入的典型场景——依赖关系复杂、需要清晰解耦。项目使用 Dagger 2.21版本集中声明在 dependencies.gradle 中。3 分钟理解 Dagger 2 依赖注入核心概念 在动手之前先搞懂 Dagger 2 依赖注入的 4 个核心角色概念作用一句话理解Component依赖容器依赖图的总指挥负责组装和分发Module依赖来源声明哪些依赖从哪来Provides手动提供用工厂方法创建实例适合第三方库Binds绑定别名把实现类绑定到接口上零成本再加上Inject声明我要什么、Singleton单例和Qualifier 限定符区分同类型依赖就构成了完整的 Dagger 2 依赖注入体系。PhotoAffix 依赖注入架构全解析PhotoAffix 的依赖注入涉及 7 个关键文件分布在app、prefs、engine、utilities四个模块中每个文件各司其职。下面按搭建依赖注入的 4 个关键步骤逐步拆解。第 1 步创建 AppComponent 依赖容器一切依赖注入的起点是 AppComponent.kt。它声明了 5 个 Module 作为依赖来源并列出 3 个需要注入的消费端Singleton Component( modules [ PrefsModule::class, AppBindModule::class, UtilityModule::class, EnginesModule::class, AppProvideModule::class ] ) interface AppComponent { fun inject(mainActivity: MainActivity) fun inject(settingsLayout: SettingsLayout) fun inject(imageSpacingDialog: ImageSpacingDialog) Component.Builder interface Builder { BindsInstance fun application(application: Application): Builder fun build(): AppComponent } }要点Component.Builder中的BindsInstance application(...)是入口参数——Application 实例由外部传入成为整个依赖图的根基。第 2 步在 Application 启动时构建组件App.kt 在应用启动的一瞬间构建 Dagger 组件appComponent DaggerAppComponent.builder() .application(this) .build()注意类名DaggerAppComponent是Dagger 编译器自动生成的无需手写。App 还实现了 Injector.kt 中的injectInto(target)接口通过when (target)把不同对象分发到对应的inject()方法让注入入口统一收口。第 3 步用 Module 划分职责边界PhotoAffix 的 5 个 Module 恰好展示了两种提供依赖的方式①Binds接口绑定实现类AppBindModule.kt、EnginesModule.kt、UtilityModule.kt 都遵循同一模式——把Real*实现绑定到接口Binds Singleton abstract fun providePhotoLoader(realPhotoLoader: RealPhotoLoader): PhotoLoader抽象方法abstract funBinds意味着实例由 Dagger 自动构造你只需要告诉它谁实现谁。②Provides手动创建复杂实例PrefsModule.kt 和 AppProvideModule.kt 则适合需要参数或特殊逻辑的场景Provides Singleton fun provideRxkPrefs(app: Application): RxkPrefs { return rxkPrefs(app, KEY_PREFERENCES) }AppProvideModule 还提供了一个巧妙用法——把协程调度器也交给 Dagger 管理Provides Singleton MainDispatcher fun provideMainDispatcher(): CoroutineContext Dispatchers.Main Provides Singleton IoDispatcher fun provideIoDispatcher(): CoroutineContext Dispatchers.IO第 4 步消费端接收注入看 MainActivity.kt 如何伸手要依赖Inject lateinit var presenter: MainPresenter Inject lateinit var affixEngine: AffixEngine override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (application as App).appComponent.inject(this) // 触发注入 ... }而MainPresenter的实现类 MainPresenter.kt 通过Inject构造函数自动装配依赖无需任何new操作class RealMainPresenter Inject constructor( private val ioManager: IoManager, private val photoLoader: PhotoLoader ) : MainPresenter 这就是依赖注入的魅力MainActivity 只依赖接口具体实现由 Dagger 2 在运行时决定——想替换实现或写单元测试改 Module 即可业务代码零改动。Qualifier 限定符如何区分同类型依赖 当同一类型有多个实例时Dagger 需要名牌来区分。PrefQualifiers.kt 定义了 5 个自定义限定符Qualifier Retention(RUNTIME) annotation class ImageSpacingVertical每个PrefInt类型都长一样但加上ImageSpacingVertical、ImageSpacingHorizontal、StackHorizontally等限定符后Dagger 就能精确区分纵向间距和横向间距这两个完全不同的偏好。同样的手法也用于 IoDispatcher.kt 区分 Main 与 IO 调度器。⚠️新手注意自定义限定符必须同时加Qualifier和Retention(RUNTIME)少写一个都会导致编译或运行异常。新手常见 3 个疑问 ❓Q1DaggerAppComponent 是谁生成的Dagger 的 Gradle 插件com.google.dagger在编译期扫描Component接口自动生成带Dagger前缀的类。你只需编写声明绝不该手写生成代码。Q2Binds和Provides怎么选简单规则实现类可以直接new出来 → 用Binds更简洁高效需要参数、条件逻辑或包装第三方类 → 用Provides。PhotoAffix 两种都用到了。Q3为什么用lateinit var接收注入Inject lateinit是字段注入的标准写法Dagger 会在inject(this)调用后填充值。缺点是绕过编译器检查更严格的团队会改用构造函数注入如RealMainPresenter的写法。总结PhotoAffix 的 Dagger 2 依赖注入架构亮点 ✅亮点说明单一 Component整个应用只需一个 AppComponent管理简单Module 按模块拆分每个子模块自带 Module解耦彻底双轨提供方式Binds管接口实现Provides管复杂构造Qualifier 规范化同类型依赖用限定符区分语义清晰协程调度器注入化Dispatchers 也纳入依赖图替换测试更方便从 PhotoAffix 的这套 Dagger 2 依赖注入实践中可以看出依赖注入不是炫技而是当你的 Android 应用模块越来越多、依赖关系越来越复杂时让代码可组装、可测试、可替换的基础设施。建议直接对照上述 7 个源码文件跟读一遍Dagger 2 依赖注入从此不再陌生。【免费下载链接】photo-affix Stitch your photos together vertically or horizontally easily!项目地址: https://gitcode.com/gh_mirrors/ph/photo-affix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考