MVP和Dagger 2-Android应用程序框架-第2部分

本文是研究的结果,其副产品是一个长期想法在一个非常有用且一度失踪的Android应用程序-My Location Notifier中的体现 ,该应用程序旨在自动通知接收者用户的到来(请参见此处的详细说明)。

因此, 在第一部分中,我们根据MVP架构构建了Android应用程序的主要框架。 现在,让我们开始将Dagger 2固定在它上面。

2.1。 预设值

首先,转到build.gradle文件(项目:mymvcapp),并将以下行添加到buildscript部分:

ext.dagger2_version = "2.8" 

在撰写本文时,这是Dagger 2的最新版本。接下来,转到build.gradle文件(模块:app)并将行添加到开头:

 apply plugin: 'kotlin-kapt' 

这是必需的,以便在Dagger 2中可以在编译时生成其代码。 稍后您将了解原因。

现在添加必要的依赖项:

 implementation "com.google.dagger:dagger:$dagger2_version" kapt "com.google.dagger:dagger-compiler:$dagger2_version" 

2.2。 注射准备

我们将同步项目并返回MainScreen组件。 在后台程序包中创建一个类di.MainScreenModule,并用Module批注对其进行标记。 在新类中,我们声明并实现ProvidePresenter()方法:MainScreenPresenter = MainScreenPresenter,并使用ProvidesSingleton批注对其进行标记。 因此,现在我们的课程将看起来:

 @Module class MainScreenModule { @Provides @Singleton fun providesPresenter(): MainScreenPresenter = MainScreenPresenter() } 

现在,我们将转到MainScreenCompatActivity类,并用lateinit var替换presenter变量的修饰符,删除值分配并用Inject注释进行标记:

 class MainScreen : BaseCompatActivity(), MainScreenContract.View { @Inject lateinit var presenter: MainScreenPresenter override fun init(savedInstanceState: Bundle?) { setContentView(R.layout.activity_main_screen) presenter.attach(this) } } 

请注意,现在访问此变量时不需要问号。
似乎所有内容都已注入,任务已完成。 但是没有 现在我们需要让Dagger生成必要的代码以注入我们的第一个依赖项。 这就是为什么我们在上面的构建脚本中添加了kotlin-kapt插件。 在com.caesar84mx.mymvcapp程序包中,创建di.config程序包,我们将在其中创建AppDiComponent接口。



现在,让我们将接口声明为一个组件,一个单例和一个悲惨的接口,在其中注册我们的模块,并在接口内部声明inject方法(mainScreenActivity:MainScreen):

 @Component( modules = [ MainScreenModule::class ] ) @Singleton interface AppDiComponent { fun inject(mainScreenActivity: MainScreen) } 

现在,您必须最终使Dagger生成所有必要的代码。 为此,我们将在config.di包中创建MyMvpApp类,从Application类继承它,并通过在application标签中写行android:name =“。Config.di.MyMvpApp”在AndroidManifest.xml中注册该类。 接下来,声明变量Lateinit var注入器:AppDiComponent,将其设置为私有setter,然后重新定义onCreate()方法。 并开始魔术:

 class MyMvpApp: Application() { lateinit var injector: AppDiComponent private set override fun onCreate() { super.onCreate() injector = DaggerAppDiComponent.builder() .mainScreenModule(MainScreenModule()) .build() } } 

如您所见,DaggerAppDiComponent类尚不存在,它将在构建应用程序期间生成。 以及我们组件的执行。 类名称由单词“ Dagger” +标记为组件的接口名称组成。 mainScreenModule()方法还将在项目的构建过程中生成,该名称应由lowerCamelCase中注入的模块的类名称组成。

我们组装项目(Build→Make Project)。 享受自动代码生成并继续。

2.3。 射出

注意:此外,还将表演一些带有色情元素的手鼓舞蹈。 从屏幕上删除儿童和紧张人士的请求。

为了成功进行进样,我们需要引用进样器变量。 同意,在我们注入的每个类中创建MyMvpApp的实例并不是最好的解决方案。 因此,我们将执行以下操作:

 class MyMvpApp: Application() { lateinit var injector: AppDiComponent private set override fun onCreate() { super.onCreate() INSTANCE = this injector = DaggerAppDiComponent.builder() .mainScreenModule(MainScreenModule()) .build() } companion object { private var INSTANCE: MyMvpApp? = null @JvmStatic fun get(): MyMvpApp = INSTANCE!! } } 

呼气,返回MainScreen类。 现在,将演示者注入init()方法。 不要忘记必须在首次访问注入变量之前执行此操作。 所以现在我们的班级看起来像:

 class MainScreen : BaseCompatActivity(), MainScreenContract.View { @Inject lateinit var presenter: MainScreenPresenter override fun init(savedInstanceState: Bundle?) { setContentView(R.layout.activity_main_screen) MyMvpApp.get().injector.inject(this) presenter.attach(this) } } 

这是我们应用程序的整个基本结构:



2.4。 结论

因此,我们已经为应用程序的最小结构做好了准备,在该结构上仅保留元素即可。 需要新活动吗? 我们将其表示为一个组件,将ui与后台分开,为每个组件确定所需的依赖项(最小,活动中的演示者,或者在演示者本身中用于与远程服务进行交互的API,例如,用于与数据库一起工作的存储库API),向模块注册依赖项,在组件中注册模块,在构建器中注册,重建项目,在必要时注入依赖项,为每个新组件重复迭代。

当然,可能会出现问题:为什么我们需要匕首? 毕竟,他们做得很好,对吗? 很好,而应用程序很小。 当它变得满满的,有许多活动,片段,适配器,服务器请求,数据缓存和其他奇迹时,如果您不使用依赖注入,那么在大型应用程序中将很难跟踪许多依赖。 Dagger DI框架有助于简化实现和跟踪它们的任务。

Source: https://habr.com/ru/post/zh-CN434618/


All Articles