如何在Android项目中从头开始设置DAGGERdependency injection?

如何使用匕首? 如何configurationDagger在我的Android项目中工作?

我想在我的Android项目中使用Dagger,但我觉得很困惑。

编辑:Dagger2自2015年5月15日也出来,它更令人困惑!

[这个问题是一个“存根(stub)”,当我学习了更多关于Dagger1的内容并且学习了更多关于Dagger2的信息的时候,我将其添加到了我的答案中。 这个问题更多的是一个指导,而不是一个“问题”。]

匕首2.x指南(修订版6)

步骤如下:

1.)Dagger添加到您的build.gradle文件中:

  • 顶级build.gradle

 // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.0' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' //added apt for source code generation } } allprojects { repositories { jcenter() } } 
  • 应用程序级别build.gradle

 apply plugin: 'com.android.application' apply plugin: 'com.neenbedankt.android-apt' //needed for source code generation android { compileSdkVersion 24 buildToolsVersion "24.0.2" defaultConfig { applicationId "your.app.id" minSdkVersion 14 targetSdkVersion 24 versionCode 1 versionName "1.0" } buildTypes { debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { apt 'com.google.dagger:dagger-compiler:2.7' //needed for source code generation compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:24.2.1' compile 'com.google.dagger:dagger:2.7' //dagger itself provided 'org.glassfish:javax.annotation:10.0-b28' //needed to resolve compilation errors, thanks to tutplus.org for finding the dependency } 

2.)创build提供依赖关系的AppContextModule类。

 @Module //a module could also include other modules public class AppContextModule { private final CustomApplication application; public AppContextModule(CustomApplication application) { this.application = application; } @Provides public CustomApplication application() { return this.application; } @Provides public Context applicationContext() { return this.application; } @Provides public LocationManager locationService(Context context) { return (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); } } 

3.)创build提供接口的AppContextComponent类,以获得可注入的类。

 public interface AppContextComponent { CustomApplication application(); //provision method Context applicationContext(); //provision method LocationManager locationManager(); //provision method } 

3.1。)这是你如何创build一个实现模块:

 @Module //this is to show that you can include modules to one another public class AnotherModule { @Provides @Singleton public AnotherClass anotherClass() { return new AnotherClassImpl(); } } @Module(includes=AnotherModule.class) //this is to show that you can include modules to one another public class OtherModule { @Provides @Singleton public OtherClass otherClass(AnotherClass anotherClass) { return new OtherClassImpl(anotherClass); } } public interface AnotherComponent { AnotherClass anotherClass(); } public interface OtherComponent extends AnotherComponent { OtherClass otherClass(); } @Component(modules={OtherModule.class}) @Singleton public interface ApplicationComponent extends OtherComponent { void inject(MainActivity mainActivity); } 

注意:您需要在模块的@Provides注释方法上提供@Scope注释(如@ActivityScope@ActivityScope ),以便在您生成的组件中获得一个范围提供程序,否则它将被取消范围,您将得到一个新的实例每次注射。

3.2)创build一个应用程序范围的组件,它指定你可以注入什么(这与Dagger 1.x中的injects={MainActivity.class} ):

 @Singleton @Component(module={AppContextModule.class}) //this is where you would add additional modules, and a dependency if you want to subscope public interface ApplicationComponent extends AppContextComponent { //extend to have the provision methods void inject(MainActivity mainActivity); } 

3.3)对于您可以通过构造函数自己创build的依赖关系,不想使用@Module重新定义(例如,您使用构build版本来改变实现types),则可以使用@Inject注释构造函数。

 public class Something { OtherThing otherThing; @Inject public Something(OtherThing otherThing) { this.otherThing = otherThing; } } 

另外,如果使用@Inject构造函数,则可以使用字段注入而不必显式调用component.inject(this)

 public class Something { @Inject OtherThing otherThing; @Inject public Something() { } } 

这些@Inject构造函数类自动添加到相同作用域的组件中,而不必在模块中明确指定它们。

@Singleton作用域@Inject构造函数类将在@Singleton作用域组件中看到。

 @Singleton // scoping public class Something { OtherThing otherThing; @Inject public Something(OtherThing otherThing) { this.otherThing = otherThing; } } 

3.4)为给定的接口定义了特定的实现之后,就像这样:

 public interface Something { void doSomething(); } @Singleton public class SomethingImpl { @Inject AnotherThing anotherThing; @Inject public SomethingImpl() { } } 

您需要使用@Module将特定实现“绑定”到接口。

 @Module public class SomethingModule { @Provides Something something(SomethingImpl something) { return something; } } 

从Dagger 2.4开始,这个简短的说法如下:

 @Module public abstract class SomethingModule { @Binds abstract Something something(SomethingImpl something); } 

4.)创build一个Injector类来处理你的应用程序级组件(它取代了单一的ObjectGraph

(注意:使用APT Rebuild Project以创buildDaggerApplicationComponent构build器类)

 public enum Injector { INSTANCE; ApplicationComponent applicationComponent; private Injector(){ } static void initialize(CustomApplication customApplication) { ApplicationComponent applicationComponent = DaggerApplicationComponent.builder() .appContextModule(new AppContextModule(customApplication)) .build(); INSTANCE.applicationComponent = applicationComponent; } public static ApplicationComponent get() { return INSTANCE.applicationComponent; } } 

5.)创build你的CustomApplication

 public class CustomApplication extends Application { @Override public void onCreate() { super.onCreate(); Injector.initialize(this); } } 

6.)CustomApplication添加到您的AndroidManifest.xml

 <application android:name=".CustomApplication" ... 

7.)MainActivity注入你的类

 public class MainActivity extends AppCompatActivity { @Inject CustomApplication customApplication; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Injector.get().inject(this); //customApplication is injected from component } } 

8.)享受!

+1)。您可以为您的组件指定Scope ,您可以使用它创build活动级范围的组件 。 子类允许您提供依赖关系,只需要给定的子范围,而不是整个应用程序。 通常情况下,每个活动获得自己的模块与此设置。 请注意, 每个组件都有一个作用域提供程序,这意味着为了保留该活动的实例,组件本身必须经历configuration更改。 例如,它可以通过onRetainCustomNonConfigurationInstance()或者一个Mortar范围来生存。

有关更多信息,请查看Google的指南 。 另请参阅本网站关于提供方法和组件依赖性部分 )和在这里 。

要创build自定义范围,您必须指定范围限定符注释:

 @Scope @Retention(RetentionPolicy.RUNTIME) public @interface YourCustomScope { } 

要创build子范围,您需要指定组件的范围,并指定ApplicationComponent作为其依赖项。 显然你也需要在模块提供者方法上指定子范围。

 @YourCustomScope @Component(dependencies = {ApplicationComponent.class}, modules = {CustomScopeModule.class}) public interface YourCustomScopedComponent extends ApplicationComponent { CustomScopeClass customScopeClass(); void inject(YourScopedClass scopedClass); } 

 @Module public class CustomScopeModule { @Provides @YourCustomScope public CustomScopeClass customScopeClass() { return new CustomScopeClassImpl(); } } 

请注意,只能将一个有作用域的组件指定为依赖项。 想想看,就像Java中不支持多重inheritance一样。

+2。)关于@Subcomponent :本质上,作用域@Subcomponent可以replace组件依赖关系; 而不是使用注释处理器提供的构build器,则需要使用组件工厂方法。

所以这:

 @Singleton @Component public interface ApplicationComponent { } @YourCustomScope @Component(dependencies = {ApplicationComponent.class}, modules = {CustomScopeModule.class}) public interface YourCustomScopedComponent extends ApplicationComponent { CustomScopeClass customScopeClass(); void inject(YourScopedClass scopedClass); } 

变成这样:

 @Singleton @Component public interface ApplicationComponent { YourCustomScopedComponent newYourCustomScopedComponent(CustomScopeModule customScopeModule); } @Subcomponent(modules={CustomScopeModule.class}) @YourCustomScope public interface YourCustomScopedComponent { CustomScopeClass customScopeClass(); } 

和这个:

 DaggerYourCustomScopedComponent.builder() .applicationComponent(Injector.get()) .customScopeModule(new CustomScopeModule()) .build(); 

变成这样:

 Injector.INSTANCE.newYourCustomScopedComponent(new CustomScopeModule()); 

+3):请检查其他关于Dagger2的Stack Overflow问题,他们提供了很多信息。 例如,我的当前Dagger2结构是在这个答案中指定的。

谢谢

感谢Github , TutsPlus , Joe Steele , Froger MCS和Google的指导 。

另外对于这个一步一步的移植指南,我写这篇文章后发现。

和基里尔的范围解释 。

更多的官方文档资料 。

匕首1.x指南:

步骤如下:

1.)将Dagger添加到依赖关系的build.gradle文件中

 dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) ... compile 'com.squareup.dagger:dagger:1.2.2' provided 'com.squareup.dagger:dagger-compiler:1.2.2' 

另外,添加packaging-option以防止有关duplicate APKs的错误。

 android { ... packagingOptions { // Exclude file to avoid // Error: Duplicate files during packaging of APK exclude 'META-INF/services/javax.annotation.processing.Processor' } } 

2.)创build一个Injector类来处理ObjectGraph

 public enum Injector { INSTANCE; private ObjectGraph objectGraph = null; public void init(final Object rootModule) { if(objectGraph == null) { objectGraph = ObjectGraph.create(rootModule); } else { objectGraph = objectGraph.plus(rootModule); } // Inject statics objectGraph.injectStatics(); } public void init(final Object rootModule, final Object target) { init(rootModule); inject(target); } public void inject(final Object target) { objectGraph.inject(target); } public <T> T resolve(Class<T> type) { return objectGraph.get(type); } } 

3.)创build一个RootModule将未来的模块链接在一起。 请注意,您必须包含injects来指定您将使用@Inject注释的每个类,否则Dagger抛出RuntimeException

 @Module( includes = { UtilsModule.class, NetworkingModule.class }, injects = { MainActivity.class } ) public class RootModule { } 

4.)如果您的根中指定了模块中的其他子模块,请为这些模块创build模块:

 @Module( includes = { SerializerModule.class, CertUtilModule.class } ) public class UtilsModule { } 

5.)创build接收依赖项作为构造函数参数的叶子模块。 在我的情况下,没有循环依赖,所以我不知道匕首是否可以解决这个问题,但我觉得不太可能。 构造函数的参数也必须在Dagger模块中提供,如果指定了complete = false那么它也可以在其他模块中。

 @Module(complete = false, library = true) public class NetworkingModule { @Provides public ClientAuthAuthenticator providesClientAuthAuthenticator() { return new ClientAuthAuthenticator(); } @Provides public ClientCertWebRequestor providesClientCertWebRequestor(ClientAuthAuthenticator clientAuthAuthenticator) { return new ClientCertWebRequestor(clientAuthAuthenticator); } @Provides public ServerCommunicator providesServerCommunicator(ClientCertWebRequestor clientCertWebRequestor) { return new ServerCommunicator(clientCertWebRequestor); } } 

6.)扩展Application并初始化Injector

 @Override public void onCreate() { super.onCreate(); Injector.INSTANCE.init(new RootModule()); } 

7.)在你的MainActivity ,在onCreate()方法中调用Injector。

 @Override protected void onCreate(Bundle savedInstanceState) { Injector.INSTANCE.inject(this); super.onCreate(savedInstanceState); ... 

8.)在你的MainActivity使用@Inject

 public class MainActivity extends ActionBarActivity { @Inject public ServerCommunicator serverCommunicator; ... 

如果你得到的错误no injectable constructor found ,请确保你没有忘记@Provides注释。