如果我想通过Dagger 2注入这个存储库,但是我希望它对于其他存储库实现是可替换的(我在避免使用“模块化”这个词),或者我希望它可以在其他组件上使用,那么我应该将它创建为存储库模块还是存储库子组件呢?
什么时候应该使用模块,什么时候应该使用子组件来实现模块化?
模块代表了一组相关的功能和绑定,可能就是您要找的。通过创建一个文档化的、可重用的模块,您封装了创建存储库的责任,允许其他开发人员或团队在不知道如何或在哪里创建存储库的情况下消费存储库。您甚至可以选择将存储库包的构造函数设置为私有的,这样您就可以控制如何使用它。
与Dagger 1不同,Dagger 2期望模块不一定是完整的:它们可以引用自己没有定义或指定的绑定。因此,如果您想要创建一个依赖于外部组件的可重用模块,您可能想要记录它需要从外部绑定的类型。(当然,您也可以使用module.includes自己指定,但这会阻止使用者在选择依赖项时使用您的模块。替换依赖项可能是测试策略的重要部分,例如对于使用假网络后端的集成测试。)
相反,子组件通常表示不同的作用域和生命周期。在Android应用程序中,这可能是服务、活动或片段的生存期,但您也可以定义自己的作用域:您也可以选择一些作用域来表示用户的登录作用域(即,在用户登录时使用相同的对象,但在用户注销或以其他人身份登录时使用新的对象)。
但是,这两种选择并不是非此即彼,特别是在使用子组件进行封装时。如果您的存储库需要许多您不希望从应用程序的其余部分注入的绑定,您可以选择将这些绑定绑定到仅包含在子组件中的模块中。看起来应该是这样的:
@Provides Repository provideRepository(RepositorySubcomponent subcomponent) {
return subcomponent.getRepository(); // defined on the subcomponent
}
类似地,您可能还需要在子图中绑定特定的绑定。也许您的应用程序需要两个独立的存储库后端,具有两个独立的存储实例。这可能是创建可重用存储库的一个问题,因为同一个图不能为同一个绑定注入不同的后端。(这有时被称为“机器腿”问题,想象一个机器人使用相同的腿和膝盖,但左右脚不同。)对于子组件,您可以选择使后端成为构建器的一部分:
@Provides @Foo Repository provideFooRepository(
RepositorySubcomponent.Builder builder,
StoneTabletStorage stoneTabletStorage) {
// Inject and use the builder instead, since we're passing in a required value.
// In this example, you'd need to define a method on the builder,
// @BindsInstance Builder storage(Storage storageImpl);
return builder
.storage(stoneTabletStorage)
.build()
.getRepository();
}
@Provides @Bar Repository provideBarRepository(
RepositorySubcomponent.Builder builder,
HolographicQubitStorage holographicQubitStorage) {
return subcomponent
.storage(holographicQubitStorage)
.build()
.getRepository();
}
...或为每个组件定义单独的子组件:
@Subcomponent(modules = {RepositoryModule.class, StoneTabletStorageModule.class})
public interface FooSubcomponent {
Repository getFooRepository();
}
@Subcomponent(modules = {RepositoryModule.class, HolographicQubitStorageModule.class})
public interface BarSubcomponent {
Repository getBarRepository();
}
您还可以通过在modules.subcomponents上列出子组件来组合这些技术,从而创建一个可重用的模块,该模块根据需要安装子组件。这允许子组件成为模块的实现细节,为您提供更大的灵活性来更改模块,同时保留其他开发人员和团队使用的绑定。
我的应用程序中有以下Dagger2架构: 其中:AppComponent: UserComponent: ActivityComponent: ChatComponent: 首先,如何将不同的注入到类中?要么是应用程序,要么是活动?? 其次,我在编译代码时遇到了一个奇怪的问题,错误是: 错误:(23,10)错误:br.com.animaeducacao.ulife.domain.interacto
我正在使用MVP架构,我需要为不同的活动注入不同的演示者。为此,我创建了@ActivityScope。这是否意味着我必须为每个活动创建一个单独的模块/组件? 如果我仍然负责创建和释放那些依赖项,那么自定义范围注释的目的是什么?不确定我是否正确,但我可以在所有模块/组件中使用@scope123,这不会有任何区别。
有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目。 也许是第三方库,或者你独立开发的,用于多个父项目的库。 现在问题来了:你想要把它们当做两个独立的项目,同时又想在一个项目中使用另一个。 我们举一个例子。 假设你正在开发一个网站然后创建了 Atom 订阅。 你决定使用一个库,而不是写自己的 Atom 生成代码。 你可能不得不通过 CPAN 安装或 Ruby gem 来包含共享库中的
一个大项目通常由很多较小的, 自完备的模块组成. 例如, 一个嵌入式Linux发行版的代码树会包含每个进行过本地修改的软件的代码; 一个电影播放器可能需要基于一个知名解码库的特定版本完成编译; 数个独立的程序可能会共用同一个创建脚本. 在集中式版本管理系统中, 可以通过把每个模块放在一个单独的仓库中来完成上述的任务. 开发者可以把所有模块都签出(checkout), 也可以选择只签出他需要的模块.
在项目开发时,你有可能经常性地想要去引用一些库文件或其它资源文件。手动的方法就是直接下载那些必要的代码文件,然后拷贝到你的项目中,最后将这些新的文件提交到你的 Git 仓库中去。 虽然这是一种有效的方法,但是这种操作并不是最简单有效的。如果只是任意地将这些库文件提交到你的项目中,将带来一系列的问题: 外部代码和自己开发的代码会被合并保存在一个项目中。其实那些库文件自身就应该是一个项目,并且也应该独
MyApp和MyAppCore有自己的AppComponent,MyApp提供ViewModel工厂,MyAppCore提供数据库和网络访问工厂(下面的示例)。 我不确定如何链接AppComponent(或应用程序),以便在MyApp中提供数据库和网络访问。以下是我目前掌握的信息: MyAppCore模块 MyAppCore还具有名为的Room数据库实现和接口(我认为我不需要在这个问题中添加此代码