使用 DispatchingAndroidInjector<> 和其他 dagger.android 类 有什么好处?
What are the advantages of using DispatchingAndroidInjector<> and the other dagger.android classes?
我正在努力将 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;
}
}
那么,我的问题是:
哪个比较好?
选择一种方法而不是另一种方法的原因是什么?
现在官方Dagger 2 documentation规定的为Android设置Dagger 2的方法有很多优点,应该优先考虑。优点只是那里阐述的那些,即:
Copy-pasting code makes it hard to refactor later on. As more and more developers copy-paste that block, fewer will know what it actually does.
More fundamentally, it requires the type requesting injection (FrombulationActivity) to know about its injector. Even if this is done through interfaces instead of concrete types, it breaks a core principle of dependency injection: a class shouldn’t know anything about how it isinjected.
让我们将这些原因应用到您的第一个示例中。
原因 1
假设我们有一个 Activity 想要使用您的 NetComponent
。我们称它为 NetActivity
。 NetActivity
的 onCreate(Bundle savedInstanceState)
方法看起来像这样:
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
依赖注入的一大优点是注入站点不需要知道或关心他们的注入器,就像依赖不知道或关心他们的依赖者一样。到 return 到我们的 NetActivity
,我们有:
((MyApp) getApplicationContext()).getNetComponent().inject(this);
Activity“知道”它的注入器(NetComponent
),并且 Activity 现在与一个实体 MyApp
和方法 getNetComponent()
来自同。如果其中任何一个 类 改变,NetActivity
也必须改变。
在 Activity 和 Dagger 2.10 及更高版本中可用的 Fragments 中遵循新的注入方式的优点恰好与这些缺点相反:
- 你最终得到的复制粘贴代码更少
- 请求注入的类型不再需要知道或关心他们的注入器或注入器的来源。
此外,正如 this blog 中所指出的,优先使用子组件而不是依赖组件可以减少应用程序的方法数。
虽然使用子组件最初可能看起来比较困难,但有一些明显的优势。但是,出于学习 Dagger 依赖组件的目的,最初可能更容易理解。如果第二个例子一开始太复杂,你可以在掌握技巧后逐步转向首选方法。
我正在努力将 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;
}
}
那么,我的问题是:
哪个比较好?
选择一种方法而不是另一种方法的原因是什么?
现在官方Dagger 2 documentation规定的为Android设置Dagger 2的方法有很多优点,应该优先考虑。优点只是那里阐述的那些,即:
Copy-pasting code makes it hard to refactor later on. As more and more developers copy-paste that block, fewer will know what it actually does.
More fundamentally, it requires the type requesting injection (FrombulationActivity) to know about its injector. Even if this is done through interfaces instead of concrete types, it breaks a core principle of dependency injection: a class shouldn’t know anything about how it isinjected.
让我们将这些原因应用到您的第一个示例中。
原因 1
假设我们有一个 Activity 想要使用您的 NetComponent
。我们称它为 NetActivity
。 NetActivity
的 onCreate(Bundle savedInstanceState)
方法看起来像这样:
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
依赖注入的一大优点是注入站点不需要知道或关心他们的注入器,就像依赖不知道或关心他们的依赖者一样。到 return 到我们的 NetActivity
,我们有:
((MyApp) getApplicationContext()).getNetComponent().inject(this);
Activity“知道”它的注入器(NetComponent
),并且 Activity 现在与一个实体 MyApp
和方法 getNetComponent()
来自同。如果其中任何一个 类 改变,NetActivity
也必须改变。
在 Activity 和 Dagger 2.10 及更高版本中可用的 Fragments 中遵循新的注入方式的优点恰好与这些缺点相反:
- 你最终得到的复制粘贴代码更少
- 请求注入的类型不再需要知道或关心他们的注入器或注入器的来源。
此外,正如 this blog 中所指出的,优先使用子组件而不是依赖组件可以减少应用程序的方法数。
虽然使用子组件最初可能看起来比较困难,但有一些明显的优势。但是,出于学习 Dagger 依赖组件的目的,最初可能更容易理解。如果第二个例子一开始太复杂,你可以在掌握技巧后逐步转向首选方法。