首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Dagger Android支持库(译文)

Dagger Android支持库(译文)

作者头像
haifeiWu
发布于 2018-09-11 02:13:20
发布于 2018-09-11 02:13:20
1.1K00
代码可运行
举报
运行总次数:0
代码可运行

与其他依赖注入框架相比,Dagger 2 最大的优点是他不使用反射,严格的生成实现类,这意味着他可以使用在 Android 应用上。但是在Android上使用仍有一些注意事项。

使用Dagger编写Android应用程序的一个主要困难是,许多Android框架类都由操作系统本身实例化,如Activity和Fragment,但如果Dagger可以创建所有注入的对象,则效果最佳。

相反,您必须在生命周期方法中执行成员注入。 这意味着许多类最终看起来像:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class FrombulationActivity extends Activity {
  @Inject Frombulator frombulator;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // DO THIS FIRST. Otherwise frombulator might be null!
    ((SomeApplicationBaseType) getContext().getApplicationContext())
        .getApplicationComponent()
        .newActivityComponentBuilder()
        .activity(this)
        .build()
        .inject(this);
    // ... now you can write the exciting code
  }
}

这有一些问题:

  1. 复制粘贴代码使得以后很难重构。 随着越来越多的开发人员复制粘贴该块,更少的人会知道它实际上做了什么。
  2. 更重要的是,它需要请求注入类型(FrombulationActivity)来了解其注入器。 即使这是通过接口而不是具体类型完成的,它也打破了依赖注入的核心原则:类不应该知道它是如何注入的。

dagger.android中的类提供了一种简化此模式的方法。

注入 Activity 对象

  1. 在应用程序组件中安装 AndroidInjectionModule,以确保这些基本类型所需的所有绑定都可用。
  2. 首先编写实现AndroidInjector 的@Subcomponent,并使用扩展AndroidInjector.Builder 的@ Subcomponent.Builder: @Subcomponent(modules = ...) public interface YourActivitySubcomponent extends AndroidInjector<YourActivity> { @Subcomponent.Builder public abstract class Builder extends AndroidInjector.Builder<YourActivity> {} }
  3. 定义子组件后,通过定义绑定子组件构建器的模块并将其添加到注入应用程序的组件,将其添加到组件层次结构中: @Module(subcomponents = YourActivitySubcomponent.class) abstract class YourActivityModule { @Binds @IntoMap @ActivityKey(YourActivity.class) abstract AndroidInjector.Factory<? extends Activity> bindYourActivityInjectorFactory(YourActivitySubcomponent.Builder builder); } @Component(modules = {..., YourActivityModule.class}) interface YourApplicationComponent {}

专业提示:如果你的 subcomponent 和他的 builder 没有其他方法或者超类型,而不是步骤2中提到的方法或超类型,则可以使用 @ContributesAndroidInjector 为您生成它们。 而不需要第2步和第3步,添加一个返回活动的抽象模块方法,使用@ContributesAndroidInjector对其进行注释,并指定要安装到子组件中的模块。 如果子组件需要范围,则还要将范围注释应用于该方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@ActivityScope
@ContributesAndroidInjector(modules = { /* modules to install into the subcomponent */ })
abstract YourActivity contributeYourActivityInjector();
  1. 接下来,让 Application 实现 HasActivityInjector 接口和 注入@Inject a DispatchingAndroidInjector ,实现 activityInjector() 方法: public class YourApplication extends Application implements HasActivityInjector { @Inject DispatchingAndroidInjector<Activity> dispatchingActivityInjector; @Override public void onCreate() { super.onCreate(); DaggerYourApplicationComponent.create() .inject(this); } @Override public AndroidInjector<Activity> activityInjector() { return dispatchingActivityInjector; } }
  2. 最后,在 Activity.onCreate() 方法,super.onCreate() 之前实现 AndroidInjection.inject(this) public class YourActivity extends Activity { public void onCreate(Bundle savedInstanceState) { AndroidInjection.inject(this); super.onCreate(savedInstanceState); } }

他是如何工作的(原理)

AndroidInjection.inject() 从 Application 获取 DispatchingAndroidInjector 并将 activity 传递给 inject(Activity)。DispatchingAndroidInjector 为您的活动类(即YourActivitySubcomponent.Builder)查找AndroidInjector.Factory,创建AndroidInjector(即YourActivitySubcomponent),并将您的活动传递给 inject(YourActivity)。

注入 Fragment 对象

注入 Fragment 就像注入 Activity 一样。以相同的方式定义 subcomponent,将 Activity 类型参数替换为 Fragment,将 @ActivityKey 替换为 @FragmentKey,将 HasActivityInjector 替换为 HasFragmentInjector。

像在 Activity 中 onCreate() 注入一样,Fragment 在 onAttach() 注入。

与为 Activitys 定义的模块不同,您可以选择在何处安装 Fragments 模块。 您可以将Fragment组件作为另一个Fragment组件,Activity组件或Application组件的子组件 - 这一切都取决于Fragment所需的其他绑定。 在确定组件位置后,使相应的类型实现 HasFragmentInjector。 例如,如果您的 Fragment 需要来自 YourActivitySubcomponent 的绑定,那么您的代码将如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class YourActivity extends Activity
    implements HasFragmentInjector {
  @Inject DispatchingAndroidInjector<Fragment> fragmentInjector;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    AndroidInjection.inject(this);
    super.onCreate(savedInstanceState);
    // ...
  }

  @Override
  public AndroidInjector<Fragment> fragmentInjector() {
    return fragmentInjector;
  }
}

public class YourFragment extends Fragment {
  @Inject SomeDependency someDep;

  @Override
  public void onAttach(Activity activity) {
    AndroidInjection.inject(this);
    super.onAttach(activity);
    // ...
  }
}

@Subcomponent(modules = ...)
public interface YourFragmentSubcomponent extends AndroidInjector<YourFragment> {
  @Subcomponent.Builder
  public abstract class Builder extends AndroidInjector.Builder<YourFragment> {}
}

@Module(subcomponents = YourFragmentSubcomponent.class)
abstract class YourFragmentModule {
  @Binds
  @IntoMap
  @FragmentKey(YourFragment.class)
  abstract AndroidInjector.Factory<? extends Fragment>
      bindYourFragmentInjectorFactory(YourFragmentSubcomponent.Builder builder);
}

@Subcomponent(modules = { YourFragmentModule.class, ... })
public interface YourActivityOrYourApplicationComponent { ... }

基本类型支持

因为 DispatchingAndroidInjector 在运行时通过类查找适当的 AndroidInjector.Factory,所以基类可以实现HasActivityInjector / HasFragmentInjector / etc以及调用AndroidInjection.inject()。 所有每个子类需要做的是绑定相应的 @Subcomponent。 如果您没有复杂的类层次结构,Dagger提供了一些基本类型,例如DaggerActivity和 DaggerFragment。 Dagger 还为同一目的提供了 DaggerApplication - 您需要做的就是扩展它并覆盖applicationInjector()方法以返回应该注入 Application 的组件。

也同时包括如下类型:

  • DaggerService 和 DaggerIntentService
  • DaggerBroadcastReceiver
  • DaggerContentProvider

注意:只有在AndroidManifest.xml中注册BroadcastReceiver时才应使用DaggerBroadcastReceiver。 在您自己的代码中创建BroadcastReceiver时,使用构造函数注入。

支持库

对于Android支持库的用户,dagger.android.support 包中存在相同类型。请注意,虽然支持Fragment用户必须绑定AndroidInjector.Factory <? extends android.support.v4.app.Fragment>,对于AppCompat,用户应该继续实现AndroidInjector.Factory <? extends Activity> 而不是 <? extends AppCompatActivity>(或FragmentActivity)。

集成方式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dependencies {
  compile 'com.google.dagger:dagger-android:2.x'
  compile 'com.google.dagger:dagger-android-support:2.x' // if you use the support libraries
  annotationProcessor 'com.google.dagger:dagger-android-processor:2.x'
}

注入时机

尽可能优先使用构造函数注入,因为 javac 将确保在设置之前不引用任何字段,这有助于避免NullPointerExceptions。 当需要注射成员时(如上所述),优选尽早注射。 出于这个原因,DaggerActivity 在调用 super.onCreate() 之前立即在 onCreate() 中调用 AndroidInjection.inject(),而 DaggerFragment 在 onAttach() 中执行相同操作,这也可以防止重新附加Fragment时出现不一致。

在Activity中的super.onCreate() 之前调用AndroidInjection.inject() 是至关重要的,因为对 super 的调用会在配置更改期间附加前一个活动实例中的 Fragments,从而注入 Fragments。 为了使Fragment注入成功,必须已经注入了Activity。 对于 ErrorProne 的用户,在 super.onCreate() 之后调用 AndroidInjection.inject() 是一个编译器错误。

问题

AndroidInjector.Factory 范围:

AndroidInjector.Factory 旨在成为无状态接口,因此实现者不必担心管理与将要注入的对象相关的状态。当DispatchingAndroidInjector 请求 AndroidInjector.Factory 时,它通过 Provider 执行此操作,以便它不会显式保留工厂的任何实例。 因为Dagger生成的 AndroidInjector.Builder 实现确实保留了正在注入的 Activity / Fragment / etc的实例,所以将范围应用于提供它们的方法是一个编译时错误。 如果您肯定您的 AndroidInjector.Factory 没有为注入的对象保留实例,则可以通过将 @SuppressWarnings(“dagger.android.ScopedInjectoryFactory”) 应用于模块方法来抑制此错误。

作 者:ChanghuiN

原文链接:https://cloud.tencent.com/developer/article/1333292

版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
带你解析Dagger2
Dagger2是Dagger1的分支,由谷歌公司接手开发,目前的版本是2.0。Dagger2是受到AutoValue项目的启发。 刚开始,Dagger2解决问题的基本思想是:利用生成和写的代码混合达到看似所有的产生和提供依赖的代码都是手写的样子。
老马的编程之旅
2022/06/22
9320
Android--Dagger2入门
在moudle的gradle中做如下配置,我在2.30.1版本中尝试使用构造函数注入,发现怎么编译都会报错,结果最后使用最新版本就可以了:
aruba
2021/12/06
7790
Android--Dagger2入门
Andriod-Dagger2
参考资料: https://www.jianshu.com/p/1d84ba23f4d2 https://mp.weixin.qq.com/s/lh3dgJK95cgbG-bUZfvbFA
android_薛之涛
2019/08/18
2.4K0
Android--Hilt入门
和Dagger相同,Hilt也分两种注入方式,以上篇Dagger中的代码为例子,来对比两个框架的使用区别
aruba
2021/12/16
1.7K0
Android--Hilt入门
Android |《看完不忘系列》之dagger
嗨,我是哈利迪~《看完不忘系列》将以从树干到细枝的思路分析一些技术框架,本文将对开源项目dagger进行介绍。
Holiday
2020/09/03
1.1K0
Android |《看完不忘系列》之dagger
Dagger2-从入门到精通(下)
继上篇文章,这篇我们来学习Dagger2的高级用法。如果没看上篇文章的话最好先看下上篇文章再来学习本章,因为本章是接续上篇文章来写的,直接来看的话可能效果不是很好,Dagger2入门-基本使用(上)。
g小志
2018/09/11
2.2K0
Dagger2-从入门到精通(下)
Dagger2使用攻略-基础部分
在这篇文章中,我会介绍 什么是依赖注入,Dagger2是什么,解决什么问题以及基础注解的使用
佛系编码
2018/10/10
1.9K0
Dagger2使用攻略-基础部分
Android Hilt实战初体验: Dagger替换成Hilt
在组件化AwesomeGithub项目中使用了Dagger来减少手动依赖注入代码。虽然它能自动化帮我们管理依赖项,但是写过之后的应该都会体会到它还是有点繁琐的。项目中到处充斥着Component,这让我想起了传统MVP模式的接口定义。
Rouse
2020/07/21
2K0
带你了解Android Jetpack库中的依赖注入框架:Hilt
Hilt是Google推出的一种用于Android的依赖注入(Dependency Injection,DI)框架,构建于Dagger之上,旨在简化Android应用中的依赖注入过程。通过Hilt,你可以更轻松地管理和提供依赖,显著减少DI的样板代码,并提高应用的可测试性和可维护性。
AntDream
2024/09/13
6240
带你了解Android Jetpack库中的依赖注入框架:Hilt
Hilt-依赖注入框架上手指南
Hilt 是Google 最新的依赖注入框架,其是基于Dagger研发,但它不同于Dagger。对于Android开发者来说,Hilt可以说专门为Android 打造,提供了一种将Dagger依赖项注入到Android应用程序的标准方法,而且创建了一组标准的组件和作用域,这些组件会自动集成到Android应用程序的各个生命周期中,以简化开发者的上手难度。
Petterp
2022/02/09
2.1K0
Hilt-依赖注入框架上手指南
如何使用MVP+Dagger2+RxJava+Retrofit开发(1)
概述 在2016年5,6月份开始在知乎上看到开发方法,那时候记得是看mvc,mvp,mvvm这三种开发模式区别,后面进一步了解到google在github上开源了使用这3种模式进行Android开发的demo.不同的项目有不同的情况,开发项目是找一个最适合的,而不是性能最好,开发时间最短等。 MVP是一种开发模式或者架构,RxJava与Retrofit是两个库,前面的是异步的库,后面的是提供Restful请求的库,这两个库都是为了MVP开发模式服务的。当然,他的适用场景是业务逻辑复杂的项目,也就是解决控制层
用户1148881
2018/01/17
1.7K0
Dagger2-从入门到精通(上)
最近在做项目中,用到了Dagger2,所以找了一些博客和其他的一些学习资源,算是知道如何使用了,但是对其理解还相差很远。所以这篇文章重点针对与使用,和使用中常见的一些问题。对更深层的东西我就不再这里不懂装懂了。如果以后有机会或需要会在以后学习更加深入后在另写文章。
g小志
2018/09/11
1.3K0
Dagger2-从入门到精通(上)
Jetpack Hilt 依赖注入框架上手指南
链接:https://juejin.im/post/5efdff9d6fb9a07eb7357ac9
陈宇明
2020/12/16
1.7K0
Android 使用dagger2进行依赖注入(基础篇)
0. 前言 Dagger2是首个使用生成代码实现完整依赖注入的框架,极大减少了使用者的编码负担, 本文主要介绍如何使用dagger2进行依赖注入。如果你不还不了解依赖注入,请看这一篇。 1. 简单的依赖注入 首先我们构建一个简单Android应用。我们创建一个UserModel,然后将它显示到TextView中。这里的问题是,在创建UserModel的时候,我们使用了前文所说的hard init。一旦我们的UserModel的创建方式发生了改变(比如需要传入Context对象到构造函数),我们就需要修改所有
庞小明
2018/03/09
1.3K0
轻松学,听说你还没有搞懂 Dagger2
Dagger2 确实比较难学,我想每个开发者学习的时候总是经历了一番痛苦的挣扎过程,于是就有了所谓的从入门到放弃之类的玩笑,当然不排除基础好的同学能够一眼看穿。本文的目的尝试用比较容易理解的角度去解释 Dagger2 这样东西。
Frank909
2019/01/14
2.3K0
Android | dagger细枝篇
嗨,我是哈利迪~《看完不忘系列》之dagger(树干篇)一文对dagger做了初步介绍,下面我们一起来瞅瞅dagger的一些细节。
Holiday
2020/09/03
8430
Android | dagger细枝篇
Dagger2的轻松愉悦解析
  Dagger2,依赖注入框架,一个刚接触时感觉麻烦,用久了就会“嘴上说不要,身体却很诚实”的开发润滑剂(◐‿◑)。(本文为拖更而生)
GSYTech
2018/08/22
5960
Dagger2的轻松愉悦解析
Dagger2 使用总结(二)
我们可以适当地复用Component接口,从而使逻辑更加简洁且减少不必要的重复工作,复用一般使用dependencies或者@Subcomponent,这两者比较相似,要注意区分,先看实现再总结吧:
杜金房
2020/12/21
3870
Dagger2 使用总结(二)
Dagger2从懵懂到精通,在线学习那点事儿
现在Dagger2在项目里用的越来越多了,最近花了些时间学习了一下Dagger2,这篇文章主要帮助理解Dagger2的注入实现过程,如有错误,还请指正!
java爱好者
2019/07/07
7530
Dagger2 入门解析
前言 在为dropwizard选择DI框架的时候考虑了很久。Guice比较成熟,Dagger2主要用于Android。虽然都是google维护的,但Dagger2远比guice更新的频率高。再一个是,Dagger2不同于guice的运行时注入,编译时生成代码的做法很好。提前发现问题,更高的效率。 还是那句话,百度到的dagger2资料看着一大堆,大都表层,而且和Android集成很深。很少有单独讲Dagger2的。不得已,去看官方文档。 HelloWorld 官方的example是基于maven的,由于
Ryan-Miao
2018/03/14
1.6K0
相关推荐
带你解析Dagger2
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验