我正在努力将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<YourActivity> {
@Subcomponent.Builder
public abstract class Builder extends AndroidInjector.Builder<YourActivity> {}
}
@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<Activity> dispatchingActivityInjector;
@Override
public void onCreate() {
super.onCreate();
DaggerYourApplicationComponent.create()
.inject(this);
}
@Override
public DispatchingAndroidInjector<Activity> activityInjector() {
return dispatchingActivityInjector;
}
}
所以,我的问题是:
哪一个更好?
选择一种方法而不是另一种方法的原因是什么?
答案 0 :(得分:15)
现在在官方Dagger 2 documentation中规定的为Android设置Dagger 2的方法有许多优点,应该是首选。优点正是那里阐述的优点,即:
复制粘贴代码使得以后很难重构。随着越来越多的开发人员复制粘贴该块,更少的人会知道它实际上做了什么。
- 醇>
更重要的是,它需要请求注入类型(FrombulationActivity)来了解其注入器。即使这是通过接口而不是具体类型完成的,它也打破了依赖注入的核心原则:类不应该知道它是如何被注入的。
让我们将这些理由应用到您的第一个例子中。
原因1
假设我们有一个想要使用您的NetComponent
的活动。我们称之为NetActivity
。 onCreate(Bundle savedInstanceState)
的{{1}}方法看起来像这样:
NetActivity
此代码具有分散在燕麦片上的脚趾甲剪报的所有视觉吸引力(不是我的明喻),并且最终会在您使用protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MyApp) getApplicationContext()).getNetComponent().inject(this);
}
的所有注射部位活动中进行复制粘贴。如果您使用更复杂的组件,例如docs中的此示例:
NetComponent
}
更糟糕的是。它很容易退化为一段神奇的代码,必须在整个注射站点进行复制和粘贴。如果它发生变化,很容易忘记仅更新一个站点并让您的应用程序崩溃。
原因2
依赖注入的一大优势是注射部位不需要知道或关心他们的注射器,就像依赖者不知道或不关心他们的家属一样。要返回我们的@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
,我们有:
NetActivity
活动“知道”它的注入器(((MyApp) getApplicationContext()).getNetComponent().inject(this);
),并且活动现在与结果NetComponent
和方法MyApp
相结合。如果其中任何一个类发生更改,getNetComponent()
也必须更改。
在Dagger版本2.10及其中提供的活动和碎片内注入新注入方式的优点正好与这些缺点相反:
此外,正如this blog中所指出的,更喜欢子组件而不是依赖组件会减少应用程序的方法数量。
虽然使用子组件最初看起来可能更难,但有一些明显的优势。然而,出于学习Dagger的目的,可能最初更容易理解Dagger相关组件。如果第二个例子最初过于复杂,那么当你获得技巧时,你可以毕业于首选方法。