我正在努力将Dagger 2设置到我的android项目中.这是我第一次使用这个框架,到目前为止一切顺利.但是我在你的项目中设置这个框架的方式看到了不同的方法,我想知道哪一个更好,因为我比较两者,对我来说结果有点相同.
我遵循了这个指南:https://github.com/codepath/android_guides/wiki/Dependency-Injection-with-Dagger-2
在互联网上搜索所有这些都使用这种方法.它使用@Module和@Component来定义依赖项.
你的申请最终如下:
public class MyApp extends Application {
private NetComponent mNetComponent;
@Override
public void onCreate() {
super.onCreate();
// Dagger%COMPONENT_NAME%
mNetCompOnent= DaggerNetComponent.builder()
// list of modules that are part of this component need to be created here too
.appModule(new AppModule(this)) // This also corresponds to the name of your module: %component_name%Module
.netModule(new NetModule("https://api.github.com"))
.build();
// If a Dagger 2 component does not have any constructor arguments for any of its modules,
// then we can use .create() as a shortcut instead:
// mNetCompOnent= com.codepath.dagger.components.DaggerNetComponent.create();
}
public NetComponent getNetComponent() {
return mNetComponent;
}
}
但我找到了另一种方式(我还没有测试过):https://google.github.io/dagger/android.html
它看起来完全不同,使用不同的类和注释.它使用这样的东西:
@Subcomponent(modules = ...)
public interface YourActivitySubcomponent extends AndroidInjector {
@Subcomponent.Builder
public abstract class Builder extends AndroidInjector.Builder {}
}
@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 {}
public class YourApplication extends Application implements HasDispatchingActivityInjector {
@Inject DispatchingAndroidInjector dispatchingActivityInjector;
@Override
public void onCreate() {
super.onCreate();
DaggerYourApplicationComponent.create()
.inject(this);
}
@Override
public DispatchingAndroidInjector activityInjector() {
return dispatchingActivityInjector;
}
}
所以,我的问题是:
哪一个更好?
选择一种方法而不是另一种方法的原因是什么?
David Rawson..
18
现在在官方Dagger 2文档中规定的为Android设置Dagger 2的方法有许多优点,应该是首选.优势正是那里阐述的优点,即:
复制粘贴代码使得以后很难重构.随着越来越多的开发人员复制粘贴该块,更少的人会知道它实际上做了什么.
更重要的是,它需要请求注入类型(FrombulationActivity)来了解其注入器.即使这是通过接口而不是具体类型完成的,它也打破了依赖注入的核心原则:类不应该知道它是如何被注入的.
让我们将这些理由应用到您的第一个例子中.
原因1
假设我们有一个想要使用你的活动NetComponent
.我们称之为NetActivity
.的onCreate(Bundle savedInstanceState)
的那个方法NetActivity
看起来是这样的:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MyApp) getApplicationContext()).getNetComponent().inject(this);
}
这段代码具有散落在燕麦片上的脚趾甲剪报的所有视觉吸引力(不是我的比喻),最终将复制粘贴在您使用的所有注射部位活动中NetComponent
.如果您使用更复杂的组件,例如文档中的此示例:
@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
}
更糟.它很容易退化为一段神奇的代码,必须在整个注射站点进行复制和粘贴.如果它发生变化,很容易忘记仅更新一个站点并让您的应用程序崩溃.
原因2
依赖注入的一大优势是注射部位不需要知道或关心他们的注射器,就像依赖者不知道或不关心他们的家属一样.回到我们的网站NetActivity
,我们有:
((MyApp) getApplicationContext()).getNetComponent().inject(this);
活动"知道"它的进样器(NetComponent
),并且活动现在与结石MyApp
和getNetComponent()
来自它的方法结合.如果这些类中的任何一个发生变化,NetActivity
也必须进行更改.
在Dagger版本2.10和向前版中使用活动和碎片内部注入新方法的优点正好与这些缺点相反:
您最终会获得较少的复制粘贴代码
请求注射的类型不再需要知道或关心他们的注射器或注射器的来源.
此外,正如本博客所指出的,更喜欢子组件而不是依赖组件会减少应用程序的方法数量.
虽然使用子组件最初可能看起来更难,但有一些明显的优点.然而,出于学习Dagger的目的,可能最初更容易理解Dagger相关组件.如果第二个例子最初太复杂,那么当你获得技巧时,你可以毕业于首选方法.
1> David Rawson..:
现在在官方Dagger 2文档中规定的为Android设置Dagger 2的方法有许多优点,应该是首选.优势正是那里阐述的优点,即:
复制粘贴代码使得以后很难重构.随着越来越多的开发人员复制粘贴该块,更少的人会知道它实际上做了什么.
更重要的是,它需要请求注入类型(FrombulationActivity)来了解其注入器.即使这是通过接口而不是具体类型完成的,它也打破了依赖注入的核心原则:类不应该知道它是如何被注入的.
让我们将这些理由应用到您的第一个例子中.
原因1
假设我们有一个想要使用你的活动NetComponent
.我们称之为NetActivity
.的onCreate(Bundle savedInstanceState)
的那个方法NetActivity
看起来是这样的:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MyApp) getApplicationContext()).getNetComponent().inject(this);
}
这段代码具有散落在燕麦片上的脚趾甲剪报的所有视觉吸引力(不是我的比喻),最终将复制粘贴在您使用的所有注射部位活动中NetComponent
.如果您使用更复杂的组件,例如文档中的此示例:
@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
}
更糟.它很容易退化为一段神奇的代码,必须在整个注射站点进行复制和粘贴.如果它发生变化,很容易忘记仅更新一个站点并让您的应用程序崩溃.
原因2
依赖注入的一大优势是注射部位不需要知道或关心他们的注射器,就像依赖者不知道或不关心他们的家属一样.回到我们的网站NetActivity
,我们有:
((MyApp) getApplicationContext()).getNetComponent().inject(this);
活动"知道"它的进样器(NetComponent
),并且活动现在与结石MyApp
和getNetComponent()
来自它的方法结合.如果这些类中的任何一个发生变化,NetActivity
也必须进行更改.
在Dagger版本2.10和向前版中使用活动和碎片内部注入新方法的优点正好与这些缺点相反:
您最终会获得较少的复制粘贴代码
请求注射的类型不再需要知道或关心他们的注射器或注射器的来源.
此外,正如本博客所指出的,更喜欢子组件而不是依赖组件会减少应用程序的方法数量.
虽然使用子组件最初可能看起来更难,但有一些明显的优点.然而,出于学习Dagger的目的,可能最初更容易理解Dagger相关组件.如果第二个例子最初太复杂,那么当你获得技巧时,你可以毕业于首选方法.
我认为区别在于人们可以推断出'AndroidInjection.inject(this)`的作用,因为它保持简单.在前一个例子中,以及文档中的"// DO THIS FIRST"示例中,它更加复杂,需要更多地了解该代码的作用.当事情变得那么复杂时,意味着复制/粘贴它的人可能甚至都不会努力去理解它,而且他们只是复制它,因为它是"_你应该做什么".`Injector.inject(this);`和`super.onCreate()`一样容易理解,我们都已经毫无疑问地做了.