我已经和dagger2合作了一段时间.我为每个Activity/Fragment创建一个自己的组件/模块感到困惑.请帮我澄清一下:
例如,我们有一个应用程序,该应用程序有大约50个屏幕.我们将实现遵循MVP模式的代码和用于DI的Dagger2.假设我们有50个活动和50个演示者.
在我看来,通常我们应该像这样组织代码:
创建一个AppComponent和AppModule,它将提供应用程序打开时将使用的所有对象.
@Module
public class AppModule {
private final MyApplicationClass application;
public AppModule(MyApplicationClass application) {
this.application = application;
}
@Provides
@Singleton
Context provideApplicationContext() {
return this.application;
}
//... and many other providers
}
@Singleton
@Component( modules = { AppModule.class } )
public interface AppComponent {
Context getAppContext();
Activity1Component plus(Activity1Module module);
Activity2Component plus(Activity2Module module);
//... plus 48 methods for 48 other activities. Suppose that we don't have any other Scope (like UserScope after user login, ....)
}
Run Code Online (Sandbox Code Playgroud)创建ActivityScope:
@Scope …Run Code Online (Sandbox Code Playgroud)Dagger 2即将到来,但可用的示例甚至不能立即编译,文档是Dagger 1的复制粘贴替换.
有没有人在Google的Dagger 2上有适当的应用程序示例?
我已经阅读了很多关于匕首2的帖子和教程:
http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/
https://github.com/codepath/android_guides/wiki/Dependency-Injection-with-Dagger-2
http://fernandocejas.com/2015/04/11/tasting-dagger-2-on-android/
https://github.com/konmik/konmik.github.io/wiki/Snorkeling-with-Dagger-2
等等
但我仍然对组件的生命周期以及它与模块和范围的关系感到困惑.我想确保在我只需要Singleton时不创建对象的多个实例.希望有人可以对这些有所了解:
在应用程序类中构建的组件的生命周期是什么?
在Activity或Fragment类中构建的组件的生命周期是什么?
如果我想从组件中获取单例实例,是否必须使用@Singleton或自定义范围对组件进行批注并在应用程序类中构建该组件?
如果我在应用程序类中构建一个组件,这是否意味着通过此组件可用的所有对象实例将是整个应用程序中的单例实例,直到该应用程序被终止或重新启动?
我有一个带有自定义范围的组件,比如@ActivityScope,我在一个Activity中构建该组件,在调用此活动的onDestroy()之后,通过该组件注入的对象实例会自动销毁吗?
我再一次有一个带有自定义范围的组件,比如@ActivityScope,我在ActivityA和ActivityB中构建这个组件,ActivityA和ActivityB是否会从这个组件共享相同的对象实例,或者它们将拥有自己的同一对象实例?
我看了几篇不同的文章,似乎提出了在Dagger 2中进行自定义范围的两种不同方式:
存活配置改变第2部分的MVP演示者(Github repo):
@Hello1Scope和@Hello2Scope为Hello1Fragment和Hello2Fragment分别@PerFragment.根据我的理解,似乎在方法2中,定义一个可用于所有片段(即@PerFragment)的单一范围应该是可以的.事实上(如果我错了请纠正我),似乎自定义范围的名称是无关紧要的,并且它只是创建子组件(即在应用程序,活动或片段中)的重要部分.
是否有任何用例来定义每个片段的唯一范围,例如在案例1中?
我不太确定如何用匕首来解决这个问题.让我们假设我们已经ApplicationModule提供了我们ApplicationContext
然后我们只ApplicationComponent使用这一个模块.然后,我们拥有ActivityModule并ActivityComponent依赖于它ApplicationComponent.
ActivityComponent是建立就像
ApplicationComponent component = ((MyApplication) getApplication()).getComponent();
mComponent = Dagger_ActivityComponent.builder()
.applicationComponent(component)
.activityModule(new ActivityModule(this))
.build();
Run Code Online (Sandbox Code Playgroud)
然后我注入我的活动:
mComponent.inject(this);
Run Code Online (Sandbox Code Playgroud)
现在我可以使用我内部声明的所有内容ActivityModule,但是我无法访问ApplicationModule.
所以问题是如何实现这一目标?那么当我构建依赖于另一个组件的组件时,我仍然可以从第一个组件访问模块?
我想我已经找到了解决方案,在再次重新阅读了Jake的Devoxx讲话之后,我不得不错过了,不管我想要从那个组件中提供的另一个组件模块中使用,例如我想从ApplicationModule内部使用Context ApplicationComponent我必须声明Context provideContext();并且它将可用.很酷:)
假设这里已经说过,开发人员有责任保留组件实例以实现自己的范围逻辑(因为范围方法将为给定组件返回相同的实例).
通过活动生命周期保持此组件引用的干净方法是什么?
示例:您正在实施MVP模式,因此您需要在Activity中使用Presenter.此演示者可以执行网络操作来下载项目.当设备旋转时,您的Activity将被销毁并重新创建,但您希望保持网络运行并返回预旋转演示者.
在为Presenter提供自定义PerActivity范围的组件范围是解决方案,因此您必须通过此循环保持Component实例,以便在首次启动Activity时注入相同的Presenter实例.
我们怎么处理这个?我想到了一种组件缓存(如HashMap?),它可以由Application类中的Application Component提供.
我正在尝试在我的Android项目中使用Dagger 2.对于初学者,我想分别使用两个负责注入应用程序范围和活动范围依赖关系的组件.作为基本参考,我使用了这个答案.
因此,有两种不同的方法来设置组件之间的关系:使用@Subcomponent注释和dependencies参数.
AppContextComponent工作正常.但是一旦我尝试从中注入依赖项ActivityContextComponent,我就会遇到这个构建时错误:错误:如果没有@Inject构造函数或@ Provide-或@ Produces-annotated方法,则无法提供com.example.ui.activity.MainActivity.
知道我确实有提供方法,这个错误信息坦率地没用.以下是我设法谷歌出错的其他几个可能的错误来源,但似乎并非如此:
Context).以下代码在Kotlin中,但我认为它应该非常简单.
应用程序组件
object AppContext {
// a singleton used in place of a Java static field
@JvmStatic lateinit var graph: AppContextComponent
}
@ApplicationScope @Component(modules = arrayOf(AppContextModule::class))
interface AppContextComponent {
fun inject(fragment: BaseFragment)
fun newActivityContextComponent(module: ActivityContextModule): ActivityContextComponent
}
@Module
class AppContextModule(val app: MyApplication) {
@Provides @ApplicationScope @ForApplication
fun provideContext(): Context {
return …Run Code Online (Sandbox Code Playgroud)