使用 Dagger 2 为 Android MVP 设置模块和组件 - Activity 具有多个片段
Setting Modules and Components with Dagger 2 for Android MVP - Activity with multiple fragments
我使用 Dagger 2 已经有一段时间了,但我仍在尝试解决一些问题。有一件事我还是不太擅长
正在为不同的情况设置模块和组件,例如带有多个片段的 activity。
我看过很多实现,大多数时候都有些不同。
所以,让我公开一下我目前使用 MVP 的应用程序结构,如果我的实现是否正确,我想听听一些意见。
@Module
public final class ApplicationModule {
private Context mContext;
public ApplicationModule(Context context){
mContext = context;
}
public ApplicationModule(){
mContext = null;
}
@Provides
Context provideContext(){
return mContext;
}
@Singleton
@Provides
public SharedPreferences getAppPreferences(){
return mContext.getSharedPreferences("CalorieApp",Context.MODE_PRIVATE);
}
}
@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(MainApplication mainApplication);
SharedPreferences sharedPreferences();
}
在这个 AppModule 中,我通常只设置我的应用需要的 Singleton。像 SharedPreferences 或任何与网络请求相关的东西。
这个模块和组件在某种程度上是标准的,我总是以这样的方式创建我的应用程序。
然后我为 Activity 设置我的模块和组件,这将依赖于 ApplicationComponent
@Module
public class ActivityModule {
private Activity activity;
public ActivityModule(Activity activity){
this.activity = activity;
}
@Provides
Activity provideActivity(){
return activity;
}
}
@PerActivity
@Component(dependencies = ApplicationComponent.class, modules =
ActivityModule.class)
public interface ActivityComponent {
void inject(WelcomeActivity welcomeActivity);
void inject(MainActivity mainActivity);
}
现在,MainActivity 有 3 个片段,我将为片段创建 3 个模块和 1 个组件
@Module
public class HomeFragmentModule {
private HomeFragmentContract.View mView;
public HomeFragmentModule(HomeFragmentContract.View view){
mView = view;
}
@Provides
HomeFragmentContract.View provideHomeFragmentView(){
return mView;
}
}
@Module
public class ChartsFragmentModule {
private ChartsFragmentContract.View mView;
public ChartsFragmentModule(ChartsFragmentContract.View view){
mView = view;
}
@Provides
ChartsFragmentContract.View provideChartsFragmentView(){
return mView;
}
}
@Module
public class ProfileFragmentModule {
private ProfileFragmentContract.View mView;
public ProfileFragmentModule(ProfileFragmentContract.View view){
mView = view;
}
@Provides
ProfileFragmentContract.View provideProfileFragmentContract(){
return mView;
}
}
@PerFragment
@Component(dependencies = ActivityComponent.class ,
modules = {ChartsFragmentModule.class, HomeFragmentModule.class,
ProfileFragmentModule.class})
public interface FragmentComponent {
void inject(ChartsFragment chartsFragment);
void inject(HomeFragment homeFragment);
void inject(ProfileFragment profileFragment);
}
然后我必须实例化 Dagger,首先在我的应用程序中 class 然后在每个活动和片段中
applicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.build();
例如WelcomeActivity,我这样实例化它:
DaggerActivityComponent.builder()
.activityModule(new ActivityModule(this))
.applicationComponent(((MainApplication)
getApplication()).getApplicationComponent())
.build()
.inject(this);
在 MainActivity 中,我的操作与上面相同,但我正在为其中的 activity 组件创建一个 getter。
然后在我的每个片段中我都这样实例化:
DaggerFragmentComponent.builder()
.homeFragmentModule(new HomeFragmentModule(this))
.activityComponent(((MainActivity)getActivity()).getActivityComponent())
.build()
.inject(this);
此时一切正常。我可以注入演示者和任何我想要的东西,但我不确定这是否是正确的方法。
你觉得我的实现怎么样?
我还有一个存储库 class,每个 Presenter 都将使用它来显示从 Firebase 到 UI 的信息。
你会为此创建一个组件和模块,然后让所有片段都依赖它吗?
希望我没有问太多问题,但我真的很想清理我的想法。
谢谢
你的设置很好。绝对是我看过的最好的。
我想提出一些小的改变,让您的生活在长期 运行 中变得更轻松。
子组件而不是组件依赖项:
我还没有看到指定组件之间的依赖关系比使用子组件更好的用例。
子组件可以直接访问父组件的整个对象图。这有两个好处:
- 可以轻松使用父级提供的对象(零代码)
- 使更改对象的范围变得容易(例如,将某些对象移动到应用程序组件以使其成为全局对象)
约定优于配置的一般原则适用于这种有利于子组件的情况。
无需区分Activity和Fragments:
我注意到 Activity 所需的对象图通常与 Fragments 所需的对象图非常相似。
在我的 MVC/MVP 方法中,我将 Activity 和 Fragments 指定为控制器,并且有一个 ControllerComponent 用于将依赖项注入控制器。
然而,即使使用另一种方法 MVC/MVP(或根本 none),如果您从概念上考虑它们 - Activity 和 Fragments 具有非常相似的功能。
因此,我建议使用一个组件来注入 Activity 和 Fragment。
不需要每个片段一个模块:
我已经回答了关于每个 Activity/Fragment here 有一个 component/module 的问题。请阅读该答案——它还提供了与此相关的代码示例以及上述所有建议。
恕我直言,模块应该按问题域对依赖项进行分组,而不是按将使用它们的组件。例如,电子商务应用程序可能具有以下模块:NetworkingModule
、CurrencyModule
、CartModule
、CheckoutModule
等...
实际实现示例:
我前段时间开源了自己的应用程序,恕我直言,它具有相对良好的依赖注入结构。您可以查看此结构 here.
我对这种 DI 结构的一个方面还不满意,即并非所有依赖项都按域分布在模块中。你可以做得更好。
订阅我的博客:
我觉得在这里插入这个有点不舒服,但我们现在正在录制有关 Dagger 的高级视频教程。过去一个月我们一直在编写本教程,它应该会在 2-3 周内准备就绪。
本教程将准确讨论您的要求 - 如何构建 Dagger 代码以实现可维护性。您可以在 www.techyourchance.com 订阅我的博客,以便在发布时收到通知。
希望对您有所帮助。
我使用 Dagger 2 已经有一段时间了,但我仍在尝试解决一些问题。有一件事我还是不太擅长 正在为不同的情况设置模块和组件,例如带有多个片段的 activity。 我看过很多实现,大多数时候都有些不同。
所以,让我公开一下我目前使用 MVP 的应用程序结构,如果我的实现是否正确,我想听听一些意见。
@Module
public final class ApplicationModule {
private Context mContext;
public ApplicationModule(Context context){
mContext = context;
}
public ApplicationModule(){
mContext = null;
}
@Provides
Context provideContext(){
return mContext;
}
@Singleton
@Provides
public SharedPreferences getAppPreferences(){
return mContext.getSharedPreferences("CalorieApp",Context.MODE_PRIVATE);
}
}
@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(MainApplication mainApplication);
SharedPreferences sharedPreferences();
}
在这个 AppModule 中,我通常只设置我的应用需要的 Singleton。像 SharedPreferences 或任何与网络请求相关的东西。 这个模块和组件在某种程度上是标准的,我总是以这样的方式创建我的应用程序。
然后我为 Activity 设置我的模块和组件,这将依赖于 ApplicationComponent
@Module
public class ActivityModule {
private Activity activity;
public ActivityModule(Activity activity){
this.activity = activity;
}
@Provides
Activity provideActivity(){
return activity;
}
}
@PerActivity
@Component(dependencies = ApplicationComponent.class, modules =
ActivityModule.class)
public interface ActivityComponent {
void inject(WelcomeActivity welcomeActivity);
void inject(MainActivity mainActivity);
}
现在,MainActivity 有 3 个片段,我将为片段创建 3 个模块和 1 个组件
@Module
public class HomeFragmentModule {
private HomeFragmentContract.View mView;
public HomeFragmentModule(HomeFragmentContract.View view){
mView = view;
}
@Provides
HomeFragmentContract.View provideHomeFragmentView(){
return mView;
}
}
@Module
public class ChartsFragmentModule {
private ChartsFragmentContract.View mView;
public ChartsFragmentModule(ChartsFragmentContract.View view){
mView = view;
}
@Provides
ChartsFragmentContract.View provideChartsFragmentView(){
return mView;
}
}
@Module
public class ProfileFragmentModule {
private ProfileFragmentContract.View mView;
public ProfileFragmentModule(ProfileFragmentContract.View view){
mView = view;
}
@Provides
ProfileFragmentContract.View provideProfileFragmentContract(){
return mView;
}
}
@PerFragment
@Component(dependencies = ActivityComponent.class ,
modules = {ChartsFragmentModule.class, HomeFragmentModule.class,
ProfileFragmentModule.class})
public interface FragmentComponent {
void inject(ChartsFragment chartsFragment);
void inject(HomeFragment homeFragment);
void inject(ProfileFragment profileFragment);
}
然后我必须实例化 Dagger,首先在我的应用程序中 class 然后在每个活动和片段中
applicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.build();
例如WelcomeActivity,我这样实例化它:
DaggerActivityComponent.builder()
.activityModule(new ActivityModule(this))
.applicationComponent(((MainApplication)
getApplication()).getApplicationComponent())
.build()
.inject(this);
在 MainActivity 中,我的操作与上面相同,但我正在为其中的 activity 组件创建一个 getter。
然后在我的每个片段中我都这样实例化:
DaggerFragmentComponent.builder()
.homeFragmentModule(new HomeFragmentModule(this))
.activityComponent(((MainActivity)getActivity()).getActivityComponent())
.build()
.inject(this);
此时一切正常。我可以注入演示者和任何我想要的东西,但我不确定这是否是正确的方法。
你觉得我的实现怎么样?
我还有一个存储库 class,每个 Presenter 都将使用它来显示从 Firebase 到 UI 的信息。
你会为此创建一个组件和模块,然后让所有片段都依赖它吗?
希望我没有问太多问题,但我真的很想清理我的想法。
谢谢
你的设置很好。绝对是我看过的最好的。
我想提出一些小的改变,让您的生活在长期 运行 中变得更轻松。
子组件而不是组件依赖项:
我还没有看到指定组件之间的依赖关系比使用子组件更好的用例。
子组件可以直接访问父组件的整个对象图。这有两个好处:
- 可以轻松使用父级提供的对象(零代码)
- 使更改对象的范围变得容易(例如,将某些对象移动到应用程序组件以使其成为全局对象)
约定优于配置的一般原则适用于这种有利于子组件的情况。
无需区分Activity和Fragments:
我注意到 Activity 所需的对象图通常与 Fragments 所需的对象图非常相似。
在我的 MVC/MVP 方法中,我将 Activity 和 Fragments 指定为控制器,并且有一个 ControllerComponent 用于将依赖项注入控制器。
然而,即使使用另一种方法 MVC/MVP(或根本 none),如果您从概念上考虑它们 - Activity 和 Fragments 具有非常相似的功能。
因此,我建议使用一个组件来注入 Activity 和 Fragment。
不需要每个片段一个模块:
我已经回答了关于每个 Activity/Fragment here 有一个 component/module 的问题。请阅读该答案——它还提供了与此相关的代码示例以及上述所有建议。
恕我直言,模块应该按问题域对依赖项进行分组,而不是按将使用它们的组件。例如,电子商务应用程序可能具有以下模块:NetworkingModule
、CurrencyModule
、CartModule
、CheckoutModule
等...
实际实现示例:
我前段时间开源了自己的应用程序,恕我直言,它具有相对良好的依赖注入结构。您可以查看此结构 here.
我对这种 DI 结构的一个方面还不满意,即并非所有依赖项都按域分布在模块中。你可以做得更好。
订阅我的博客:
我觉得在这里插入这个有点不舒服,但我们现在正在录制有关 Dagger 的高级视频教程。过去一个月我们一直在编写本教程,它应该会在 2-3 周内准备就绪。
本教程将准确讨论您的要求 - 如何构建 Dagger 代码以实现可维护性。您可以在 www.techyourchance.com 订阅我的博客,以便在发布时收到通知。
希望对您有所帮助。