gpt4 book ai didi

java - Dagger 2 问题覆盖单个提供来自应用程序使用的库中模块的注释方法

转载 作者:搜寻专家 更新时间:2023-10-30 21:05:12 26 4
gpt4 key购买 nike

GitHub 项目链接

我做了一个project on GitHub这是我的项目实际架构的 Dagger 2 架构模型。这个问题将基于 GitHub 项目。

我在这个问题中提供了很多代码 fragment ,但是,在 Android Studio 中自己编译项目可能更容易理解问题。

如果您 checkout 代码,它不会编译。进入 AppModule.java 并注释掉这两个提供的方法,它应该可以编译。

主要问题是这篇文章的最后一行。

https://github.com/qazimusab/Dagger2LibraryProject

架构

我有一个库,其中包含制作应用程序所需的所有代码。这种架构的要点是我在项目中创建的每个应用程序都应该能够使用该库,并且通过 dagger 2,能够为它自己的模块中它想要的任何单个类或 Activity 提供不同的实现。此时,我在这个示例项目中只有一个使用该库的应用程序。

问题

对于 dagger one,我有相同的架构,并且在特定于应用程序的模块(与库模块相对)中,我能够添加一个新的提供注释的方法来覆盖任何提供的任何实现库模块只要

  1. 该方法在应用程序模块中的一个模块中
  2. 方法用@Provides注解
  3. 该方法与您要覆盖的方法具有相同的返回类型

对于 Dagger 2,当我不覆盖任何提供或者如果我覆盖,当我覆盖该模块中的每个提供并从应用程序特定模块的包含中删除该模块时,该架构工作。

例如,在我的项目中,我有一个应用程序和一个库。

应用有一个AppModule;该库有一个 CatModule 来提供 Cat 和 CatFood,一个 dog 模块来提供 Dog 和 DogFood,还有一个 LibraryModule 来提供 Activity 。

猫模块.java

package com.example.qaziahmed.library.application.modules;

import com.example.qaziahmed.library.classes.Cat; import
com.example.qaziahmed.library.classes.CatFood; import
com.example.qaziahmed.library.classes.contract.ICat; import
com.example.qaziahmed.library.classes.contract.ICatFood;

import javax.inject.Singleton;

import dagger.Module; import dagger.Provides;

/** * Created by qaziahmed on 11/23/15. */ @Module public class
CatModule {

@Provides
@Singleton
ICat provideCat() {
return new Cat();
}

@Provides
ICatFood provideCatFood(){
return new CatFood();
} }

狗模块.java

package com.example.qaziahmed.library.application.modules;

import com.example.qaziahmed.library.classes.Dog; import
com.example.qaziahmed.library.classes.DogFood; import
com.example.qaziahmed.library.classes.contract.IDog; import
com.example.qaziahmed.library.classes.contract.IDogFood;

import javax.inject.Singleton;

import dagger.Module; import dagger.Provides;

/** * Created by qaziahmed on 11/23/15. */ @Module public class
DogModule {

@Provides
@Singleton
IDog provideDog() {
return new Dog();
}

@Provides
IDogFood provideDogFood(){
return new DogFood();
}

}

因此,在我的应用程序模块中,我想提供 ICat 的家猫实现而不是通用猫,以及 IDogFood 的 AllNaturalDogFood 实现而不是普通的 DogFood,然后在我的 AppModule 中我添加两个提供来覆盖它们

AppModule.java

package com.example.qaziahmed.dagger2libraryproject.application;

import
com.example.qaziahmed.dagger2libraryproject.classes.AllNaturalDogFood;
import com.example.qaziahmed.dagger2libraryproject.classes.HouseCat;
import com.example.qaziahmed.library.application.modules.CatModule;
import com.example.qaziahmed.library.application.modules.DogModule;
import
com.example.qaziahmed.library.application.modules.LibraryModule;
import com.example.qaziahmed.library.classes.contract.ICat; import
com.example.qaziahmed.library.classes.contract.IDogFood;

import javax.inject.Singleton;

import dagger.Module; import dagger.Provides;

/** * Created by ogre on 2015-07-12 */ @Module(includes = {
LibraryModule.class,
DogModule.class,
CatModule.class }) public class AppModule {

@Provides
@Singleton
ICat provideHouseCat() {
return new HouseCat();
}

@Provides
IDogFood provideAllNaturalDogFood(){
return new AllNaturalDogFood();
} }

现在,当我运行这个设置时,这是我得到的错误:

Error:com.example.qaziahmed.library.classes.contract.ICat is bound multiple times: @Provides @Singleton com.example.qaziahmed.library.classes.contract.ICat com.example.qaziahmed.dagger2libraryproject.application.AppModule.provideHouseCat() @Provides @Singleton com.example.qaziahmed.library.classes.contract.ICat com.example.qaziahmed.library.application.modules.CatModule.provideCat() Error:com.example.qaziahmed.library.classes.contract.IDogFood is bound multiple times: @Provides com.example.qaziahmed.library.classes.contract.IDogFood com.example.qaziahmed.dagger2libraryproject.application.AppModule.provideAllNaturalDogFood() @Provides com.example.qaziahmed.library.classes.contract.IDogFood com.example.qaziahmed.library.application.modules.DogModule.provideDogFood()

现在,如果在 AppModule.java 中,我还添加了提供注释的方法来提供 Cat Food 和 Provide Dog,然后从 App Module 的包含中删除 CatModule.class 和 DogModule.class 然后它就可以工作了。

但是,整个问题是如何覆盖库中某些模块中的单个提供方法,而不必覆盖该特定模块内的每个提供注释方法,然后从 AppModule.java 中的包含中删除该模块

最佳答案

将尝试解密 Dagger 2 文档中的这段引用:

Dagger 2 doesn't support overrides. Modules that override for simple testing fakes can create a subclass of the module to emulate that behavior. Modules that use overrides and rely on dependency injection should be decomposed so that the overridden modules are instead represented as a choice between two modules.

在您当前的示例中,您不依赖依赖注入(inject),因为您的 provides* 方法创建简单的新对象,因此您将能够创建模块的子类,覆盖 提供您需要覆盖的方法,然后在您的组件中包含该新模块。

当您依赖 DI 时(实际上您会在项目的某个阶段)像这样:

@Provides
@Singleton
ICat provideCat(IBowtie bowtie) { // 'bowtie' needs to be injected
return new CatWithBowtie(Bowtie);
}

它谈到“应该分解使用覆盖和依赖依赖注入(inject)的模块”,这基本上意味着:你必须将 CatModule 一分为二: CatModuleprovidesCat 和“CatFoodModule”与 provideCatFood()。然后您的应用程序组件您只需使用新的 CatWithBowtieModule 而不是 CatModule

有两个有用的建议:

  1. 在库项目中拆分模块,因此每个模块只有一个 provides* 方法。是的,这听起来像废话,但这是稍后在您的应用中提供轻松覆盖的唯一方法。

  2. 暂时假设该库是第三方作为 JAR/AAP 提供给您的,而您甚至没有源代码。在那种情况下,您将无法重用库中定义的模块,因此您必须自己创建所有模块。这正是 Dagger 2 所发生的事情。

当您尝试在您的应用程序中直接使用您的库中的模块时(就像您所做的那样),这两个项目不再是两个独立的项目,而是一个看起来就像两个项目的项目(它们是 clusterf*ck 紧密耦合的)。应用程序可以依赖于库,但库不能依赖于应用程序。归结为:在 Dagger 2 中最好不要使用跨(项目)边界的 modulescomponents

有人可能会问:“如果我不能在我的应用程序中使用 lib 的 modules/components,那么在 lib 中使用 Dagger 2 有什么好处?!”。好吧,您仍然可以在单元测试中使用 Dagger modules/components,毕竟这是使用 Dagger 的主要好处。此外,如果您的 lib 打算供其他人使用,您可以(必须?)提供一个引用应用程序,它显示如何“连接”事物,以便 lib 的用户能够在适合他们的情况下复制该代码,或者至少看看如何开始。

关于java - Dagger 2 问题覆盖单个提供来自应用程序使用的库中模块的注释方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33880618/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com