- 依赖注入
- 移动开发
- 后端
【免费下载链接】dagger
A fast dependency injector for Android and Java.
本指南以仓库 examples/android-simple 示例为骨架,系统讲解 Dagger(dagger 1.x 时代核心 API)在 Android 应用中的落地方式:如何用自定义Application维护全局ObjectGraph、如何用可覆写的getModules()实现开发版/测试环境的模块扩展,以及如何在基类 Activity 中自动完成注入。读完你将掌握一套可直接套用的 Android + Dagger 最小工程结构,并理解其中每个注解与配置的底层语义。
示例定位:展示结构而非业务功能
README.md 开篇即明确了该示例的边界:它演示的是"如何用 Dagger 组织一个 Android 应用",而不是一个可运行的业务 App。原文特别说明:应用运行时不会真正做任何事,它只是展示如何把 Dagger 结构化地嵌入 Android 工程。因此阅读本文时,关注点应放在依赖注入的装配模式上,而非 Activity 里的具体逻辑。
核心模式一句话概括:用自定义Application类管理一个全局对象图(Object Graph),模块通过 Application 上的getModules()方法装配,该方法可被覆写以在开发版本或测试中追加额外模块;Activity 的注入则在基类中自动完成。
工程结构与 Maven 配置
目录布局
examples/android-simple/ ├── AndroidManifest.xml(位于 src/main/) ├── pom.xml └── src/main/java/com/example/dagger/simple/ ├── AndroidModule.java // Android 专属依赖(Context、LocationManager) ├── DemoApplication.java // 自定义 Application,持有全局 ObjectGraph ├── DemoBaseActivity.java // 抽象基类,onCreate 中自动注入 ├── DemoModule.java // 业务模块占位,声明 injects 目标 ├── ForApplication.java // @Qualifier,区分 Application Context 与 Activity Context └── ui/HomeActivity.java // 具体页面,声明 @Inject 字段依赖声明(pom.xml)
pom.xml 中,android-simple模块(artifactId)以com.squareup.dagger.example:dagger-example-parent为父工程,版本为1.2.6-SNAPSHOT,打包方式为apk。依赖上需要三类东西:
- 运行时依赖
com.squareup.dagger:dagger:提供ObjectGraph、@Module、@Provides等核心 API; - 编译期注解处理器
com.squareup.dagger:dagger-compiler:标记为<optional>true</optional>,在编译阶段生成模块适配器(ModuleAdapter)等代码,运行时不需要携带; - Android SDK
com.google.android:android,scope 为provided,因为 android.jar 只在编译期使用,最终由设备/模拟器提供。
构建插件使用com.simpligility.maven.plugins:android-maven-plugin(<extensions>true</extensions>),负责将工程打包为 APK。Manifest 文件位于 src/main/AndroidManifest.xml,声明minSdkVersion=4、targetSdkVersion=17,Application 指定为.DemoApplication,启动 Activity 为.ui.HomeActivity。
核心一:自定义 Application 持有全局对象图
DemoApplication.java 是整个模式的枢纽:
public class DemoApplication extends Application { private ObjectGraph graph; @Override public void onCreate() { super.onCreate(); graph = ObjectGraph.create(getModules().toArray()); } protected List<Object> getModules() { return Arrays.asList( new AndroidModule(this), new DemoModule() ); } public void inject(Object object) { graph.inject(object); } }三个要点:
ObjectGraph.create(...)在onCreate中构建全局图:ObjectGraph是 dagger 1.x 的核心入口(源码见 core/src/main/java/dagger/ObjectGraph.java),负责把模块列表装配成一张可查询、可注入的依赖图。整个 App 生命周期内该图只创建一次。getModules()被设计为可覆写:这是本示例最关键的扩展点。生产环境下返回AndroidModule+DemoModule;在开发版或测试中,子类可覆写该方法追加TestModule之类的额外模块,从而在不改动主代码的前提下替换或补充依赖。- 暴露
inject(Object)门面方法:把graph.inject()包一层,供所有 Activity/Fragment 复用,避免业务代码直接接触ObjectGraph。
核心二:模块装配——@Module的两种语义
两个模块展示了@Module注解的两种典型配置:
AndroidModule:library = true的纯供给模块
AndroidModule.java 专门提供需要Context或Application才能创建的系统级依赖:
@Module(library = true) public class AndroidModule { private final DemoApplication application; public AndroidModule(DemoApplication application) { this.application = application; } @Provides @Singleton @ForApplication Context provideApplicationContext() { return application; } @Provides @Singleton LocationManager provideLocationManager() { return (LocationManager) application.getSystemService(LOCATION_SERVICE); } }library = true:声明该模块只"提供"依赖、不"注入"对象,允许图中存在未使用的供给(不会因某个 provider 无人消费而报错)。这与complete = false配合,表示依赖关系可以由多个模块共同补全。@Provides @Singleton:LocationManager这类系统服务在整个应用中应当是单例,因此同时标注@Singleton做作用域限定,保证每次注入拿到同一个实例。@ForApplication限定符:这是示例里最有教学价值的细节。由于 Android 中Application和Activity都实现了Context,直接注入Context会产生歧义。ForApplication是一个用@Qualifier @Retention(RUNTIME)声明的自定义注解(见 ForApplication.java),配合@ForApplication Context的@Provides方法,显式区分"注入 Application Context"与"注入 Activity Context"两种语义——这正是 Dagger 限定符(Qualifier)机制在 Android 场景的经典用法。
DemoModule:complete = false的业务占位模块
DemoModule.java 是业务侧的入口:
@Module( injects = HomeActivity.class, complete = false ) public class DemoModule { // TODO put your application-specific providers here! }injects = HomeActivity.class:显式声明本模块负责向哪些类执行注入。Dagger 编译期校验会据此确认注入目标的依赖是否齐备。complete = false:表示该模块自身不是"完整的"依赖来源,允许依赖在其它模块(如AndroidModule)中提供。这也是示例刻意为之的松耦合设计——业务模块只负责声明注入入口,系统依赖交给平台模块。- 模块本体为空、仅留 TODO 注释,说明模块的职责主要是装配与声明,具体 provider 可以按需填充。
核心三:基类 Activity 自动注入
DemoBaseActivity.java 实现了"打开页面即注入完成"的效果:
public abstract class DemoBaseActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Perform injection so that when this call returns all dependencies will be available for use. ((DemoApplication) getApplication()).inject(this); } }具体页面只需继承它并声明字段:
HomeActivity.java:
public class HomeActivity extends DemoBaseActivity { @Inject LocationManager locationManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // After the super.onCreate call returns we are guaranteed our injections are available. // TODO do something with the injected dependencies here! } }流程链路:HomeActivity启动 →super.onCreate→DemoBaseActivity从getApplication()拿到自定义DemoApplication→ 调用其inject(this)→ 触发ObjectGraph.inject按图解析并注入@Inject LocationManager。因此在super.onCreate返回之后,locationManager一定可用,这是示例在注释中反复强调的时序保证。
扩展视角:从"简单"到"子图"
示例在 Manifest 中仅声明了一个启动 Activity(src/main/AndroidManifest.xml),呈现的是"一个 Application 对应一张全局图"的最简形态。仓库中还提供了进阶版 android-activity-graphs,在该示例中每个 Activity 会基于全局图再创建子图(child graph),从而获得按 Activity 作用域注入、按页面粒度的单例、以及保持全局图干净等能力。其 README 同样注明该思想可推广到"用户会话(user session)"等自定义作用域——即根据业务生命周期动态创建专属对象图。这与本示例的getModules()可覆写设计一脉相承:模块列表的装配点(Application)越灵活,后续按作用域拆分图就越容易。
小结:可直接复用的落地清单
| 关注点 | 实现位置 | 关键语义 |
|---|---|---|
| 全局图生命周期 | DemoApplication.onCreate中ObjectGraph.create(...) | 全 App 仅创建一次 |
| 模块扩展点 | getModules()可覆写 | 开发版/测试可追加模块 |
| Android 专属依赖 | AndroidModule(library=true) | 提供 Context、系统服务 |
| Context 歧义消除 | @ForApplication限定符 | 区分 Application 与 Activity Context |
| 注入入口声明 | DemoModule(injects+complete=false) | 业务模块只管声明与装配 |
| 自动注入 | DemoBaseActivity.onCreate | super.onCreate返回后依赖即可用 |
按此结构,你可以在自己的 Android 工程中照搬四件事:① 自定义Application持有全局ObjectGraph;② 用可覆写的getModules()组装模块;③ 用基类 Activity 统一注入;④ 用@Qualifier解决多 Context 歧义。这也是该示例被保留在仓库中的价值所在——它用最小代码量讲清了 Dagger 在 Android 上的标准装配范式。
- 依赖注入
- 移动开发
- 后端
【免费下载链接】dagger
A fast dependency injector for Android and Java.
相关推荐
你的数字记忆,值得被永恒珍藏
你的数字记忆,值得被永恒珍藏 你是否曾经翻看过去的聊天记录,那些温暖的对话、重要的约定、深夜的倾诉,是否都随着手机更换或存储清理而消失?在数字时代,我们的情感与
如何快速掌握Dagger依赖注入:ObjectGraph构建依赖关系网完整指南
如何快速掌握Dagger依赖注入:ObjectGraph构建依赖关系网完整指南 Dagger是一个为Android和Java打造的快速依赖注入框架,通过Obje
依赖注入移动开发后端ZXing自定义Application场景:全局状态与单例管理
ZXing自定义Application场景:全局状态与单例管理 在ZXing(Zebra Crossing)条码扫描库的Android应用开发中,全局状态管理和
图像处理计算机视觉
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考