问题描述
我在Android应用程序中使用 Dagger2
,在我的应用程序中有两个组件.首先是整个应用程序的全局属性,其次是针对活动实例的属性.
NetComponent.java
@Singleton@Component(modules = {AppModule.class,NetModule.class})公用接口NetComponent {void inject(AuthenticationActivity authenticationActivity);无效注入(PaymentActivitypaymentActivity);}
ValidationComponent.java
@Singleton@Component(modules = {ValidatorModule.class})公共接口ValidationComponent {无效注入(活动活动);}
AppModule.java
@Module公共类AppModule {私人申请书;公共AppModule(应用程序应用){this.application =应用程序;}@提供@辛格尔顿应用程序includesApplication(){退货申请;}}
NetModule.java
@Module公共类NetModule {@提供@辛格尔顿SharedPreferences提供了SharedPreferences(应用程序应用程序){返回PreferenceManager.getDefaultSharedPreferences(application);}@提供@辛格尔顿缓存provideOkHttpCache(应用程序应用程序){int cacheSize = 10 * 1024 * 1024;//10 MiB缓存缓存=新的Cache(application.getCacheDir(),cacheSize);返回缓存;}@提供@辛格尔顿Gson ProvideGson(){GsonBuilder gsonBuilder =新的GsonBuilder();gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);返回gsonBuilder.create();}@提供@辛格尔顿OkHttpClient ProvideOkHttpClient(缓存缓存){OkHttpClient okHttpClient =新的OkHttpClient();okHttpClient.newBuilder()//.addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR).cache(缓存).建造();返回okHttpClient;}@提供@辛格尔顿@Named("authRetrofit")加装provideAuthRetrofit(Gson gson,OkHttpClient okHttpClient){改造改造=新的Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)).baseUrl(PAYMENT_SERVICE).client(okHttpClient).建造();退货改造;}@提供@辛格尔顿@Named("paymentRetrofit")加装providePaymentRetrofit(Gson gson,OkHttpClient okHttpClient){改造改造=新的Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)).baseUrl(LOGIN_SERVICE).client(okHttpClient).建造();退货改造;}}
ValidatorModule.java
@Module公共类ValidatorModule {私人最终活动活动;public ValidatorModule(活动活动){this.activity =活动;}@提供com.mobsandgeeks.saripaar.Validator includesValidator(){返回新的com.mobsandgeeks.saripaar.Validator(活动);}}
AppApplication.java
公共类AppApplication扩展了Application {私有NetComponent mNetComponent;@Override公共无效onCreate(){super.onCreate();mNetComponent = DaggerNetComponent.builder().appModule(新的AppModule(this)).建造();}公共NetComponent getmNetComponent(){返回mNetComponent;}}
AuthenticationActivity.java
公共类AuthenticationActivity扩展了BaseActivity实现的View.OnClickListener,Validator.ValidationListener {@注入验证器验证器;@Override受保护的void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);....(((AppApplication)getApplication()).getmNetComponent().inject(this);ValidationComponentvalidationComponent = DaggerValidationComponent.builder().validatorModule(getValidatorModule()).建造();validationComponent.inject(this);...//应用点击和验证监听器validateator.setValidationListener(this);}}受保护的ValidatorModule getValidatorModule(){返回新的ValidatorModule(this);}
它正在生成 ValidationComponent
,而不是 DaggerNetComponent
以上是我的模块,是我的应用程序的组件.当我编译和构建应用程序时,我遇到了以下错误-
错误
Information:Gradle任务[干净,:app:generateDebugSources,:app:mockableAndroidJar,:app:prepareDebugUnitTestDependencies,:app:generateDebugAndroidTestSources,:app:compileDebugSources,:app:compileDebugUnitTestSources,:app:compileDebugAndroidTestSources]C:\ Users \ xyz \ AndroidStudioProjects \ ICICIAppathon \ app \ src \ main \ java \ com \ icici \ iciciappathon \ AppApplication.java错误:(24、48)错误:找不到符号类DaggerNetComponentC:\ Users \ xyz \ AndroidStudioProjects \ ICICIAppathon \ app \ src \ main \ java \ com \ icici \ iciciappathon \ login \ AuthenticationActivity.java错误:(35,48)错误:找不到符号类DaggerValidationComponent错误:(39、43)错误:程序包com.icici.iciciappathon.databinding不存在C:\ Users \ xyz \ AndroidStudioProjects \ ICICIAppathon \ app \ src \ main \ java \ com \ icici \ iciciappathon \ checkout \ PaymentActivity.java错误:(28,43)错误:程序包com.icici.iciciappathon.databinding不存在C:\ Users \ xyz \ AndroidStudioProjects \ ICICIAppathon \ app \ src \ main \ java \ com \ icici \ iciciappathon \ dashboard \ DashboardActivity.java错误:(32、43)错误:程序包com.icici.iciciappathon.databinding不存在C:\ Users \ xyz \ AndroidStudioProjects \ ICICIAppathon \ app \ src \ main \ java \ com \ icici \ iciciappathon \ shopping \ ScanBarcodeActivity.java错误:(41、43)错误:程序包com.icici.iciciappathon.databinding不存在C:\ Users \ xyz \ AndroidStudioProjects \ ICICIAppathon \ app \ src \ main \ java \ com \ icici \ iciciappathon \ ui \ GetStartedActivity.java错误:(27、43)错误:程序包com.icici.iciciappathon.databinding不存在C:\ Users \ xyz \ AndroidStudioProjects \ ICICIAppathon \ app \ src \ main \ java \ com \ icici \ iciciappathon \ dagger \ component \ NetComponent.java错误:(34,10)错误:没有@Inject构造函数或@ Provides-或@ Produces-注释方法无法提供com.mobsandgeeks.saripaar.Validator.com.icici.iciciappathon.login.AuthenticationActivity.validator[类型为com.mobsandgeeks.saripaar.Validator验证器的注入字段]错误:任务':app:compileDebugJavaWithJavac'的执行失败.>编译失败;有关详细信息,请参见编译器错误输出.信息:建造失败信息:总时间:11.373秒信息:9个错误信息:0警告信息:在控制台中查看完整的输出
此处的一般说法是,当Dagger遇到错误时(通常是在绑定图中执行某些不可能的事情时),它不会生成类.就是这种情况.
我同意 azizbekian ,问题是您试图从AuthenticationActivity中注入Validator,并告诉NetComponent尝试这样做而不指示如何做(在ValidationModule中).
在您发布的代码中,没有任何理由让NetComponent注入AuthenticationActivity.没有什么可提供的.因此,您可以删除这两行并完成操作:
//在NetComponent中void inject(AuthenticationActivity authenticationActivity);//在AuthenticationActivity中((AppApplication)getApplication()).getmNetComponent().inject(this);
但是,您也可能没有向我们显示AuthenticationActivity中所需的NetComponent依赖项.在这种情况下,您将需要通过子组件或组件依赖项来组合对象图.您仍然需要删除上面列出的两行,因为在任何情况下NetComponent都不需要注入AuthenticationActivity.
子组件
要使用子组件,只需在NetComponent上构建一个构建器,您就可以通过该构建器获取您的ValidationActivity.欢迎您提供一个范围,但不一定需要一个范围,我认为将其添加到组合中可能会造成混淆.届时,您的ValidationComponent将有权访问NetComponent中的所有绑定以及ValidationComponent中列出的所有绑定.尽管值得注意的是,这是通过子组件而不是组件依赖项,但这实际上与阿兹别克人的答案相同.稍后我将讨论组件依赖性.
//删除了inject(AuthenticationActivity)调用后,将其添加到NetComponentValidatorComponentvalidatorComponent(ValidatorModulevalidatorModule);//并从AuthenticationActivity调用实现((AppApplication)getApplication()).getmNetComponent().validatorModule(新的ValidatorModule(this)).注入();
您还需要将 ValidationComponent
从 @Component
切换到 @Subcomponent
,并删除 @Singleton
实例(这很有意义,因为您正在为Android创建的每个AuthenticationActivity实例创建一个新实例.
有效地,这使NetComponent成为ValidationComponent实例的工厂.Dagger一次生成了两者的代码,因此ValidationComponent可以从NetComponent自动访问其所需的任何内容.但是,用这种方法不可能分别为每个代码生成代码,也不能在没有NetComponent实例的情况下获得ValidationComponent(除非通过将其包含在另一个组件中).
组件依赖项
组件依赖项有点起作用有点不同.它们是独立的组件,因此可以分别和独立生成.取而代之的是,您可以传入一个接口(通常但不一定是另一个Dagger组件,例如NetComponent),并且每个单独的无参数方法都将成为另一个图中的自动提供者.例如,这意味着您可以从NetComponent列出ValidationComponent可用的特定依赖项,向您的ValidationComponent定义添加 dependencies = {NetComponent.class}
,然后更改DaggerValidationComponent构建器以调用.netComponent(((((AppApplication getApplication()).getmNetComponent())
以连接确切的实例.(类似地,您可以使用该接口的任何实现来实现,无论Dagger是否生成它;这都可以帮助您您还需要删除对 @Singleton
的使用,因为Dagger会很困惑,因为有两个独立的组件都声称存在于Singleton范围内-必须首先创建一个组件,毕竟.
您尚未列出要从NetComponent中使用的确切依赖关系,因此我没有可以显示的示例更改.但是,对于这种情况,无论如何我还是建议使用子组件.绑定更加自动化,您可能不会从组件依赖关系中获得的松散耦合中受益,而且您更接近 Dagger的官方Android支持包,因此以后更容易迁移到该版本.
I am using Dagger2
in my android application, I have two component in my application. First is global for entire application and second is specific to activity instance.
NetComponent.java
@Singleton
@Component(modules = {AppModule.class, NetModule.class})
public interface NetComponent {
void inject(AuthenticationActivity authenticationActivity);
void inject(PaymentActivity paymentActivity);
}
ValidationComponent.java
@Singleton
@Component(modules = {ValidatorModule.class})
public interface ValidationComponent {
void inject(Activity activity);
}
AppModule.java
@Module
public class AppModule {
private Application application;
public AppModule(Application application) {
this.application = application;
}
@Provides
@Singleton
Application providesApplication() {
return application;
}
}
NetModule.java
@Module
public class NetModule {
@Provides
@Singleton
SharedPreferences providesSharedPreferences(Application application) {
return PreferenceManager.getDefaultSharedPreferences(application);
}
@Provides
@Singleton
Cache provideOkHttpCache(Application application) {
int cacheSize = 10 * 1024 * 1024; // 10 MiB
Cache cache = new Cache(application.getCacheDir(), cacheSize);
return cache;
}
@Provides
@Singleton
Gson provideGson() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
return gsonBuilder.create();
}
@Provides
@Singleton
OkHttpClient provideOkHttpClient(Cache cache) {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.newBuilder()
//.addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
.cache(cache)
.build();
return okHttpClient;
}
@Provides
@Singleton
@Named("authRetrofit")
Retrofit provideAuthRetrofit(Gson gson, OkHttpClient okHttpClient) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(PAYMENT_SERVICE)
.client(okHttpClient)
.build();
return retrofit;
}
@Provides
@Singleton
@Named("paymentRetrofit")
Retrofit providePaymentRetrofit(Gson gson, OkHttpClient okHttpClient) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(LOGIN_SERVICE)
.client(okHttpClient)
.build();
return retrofit;
}
}
ValidatorModule.java
@Module
public class ValidatorModule {
private final Activity activity;
public ValidatorModule(Activity activity) {
this.activity = activity;
}
@Provides
com.mobsandgeeks.saripaar.Validator providesValidator() {
return new com.mobsandgeeks.saripaar.Validator(activity);
}
}
AppApplication.java
public class AppApplication extends Application {
private NetComponent mNetComponent;
@Override
public void onCreate() {
super.onCreate();
mNetComponent = DaggerNetComponent.builder()
.appModule(new AppModule(this))
.build();
}
public NetComponent getmNetComponent() {
return mNetComponent;
}
}
AuthenticationActivity.java
public class AuthenticationActivity extends BaseActivity implements View.OnClickListener, Validator.ValidationListener {
@Inject
Validator validator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....
((AppApplication) getApplication()).getmNetComponent().inject(this);
ValidationComponent validationComponent = DaggerValidationComponent.builder()
.validatorModule(getValidatorModule())
.build();
validationComponent.inject(this);
...
// apply click and validation listeners
validator.setValidationListener(this);
}
}
protected ValidatorModule getValidatorModule() {
return new ValidatorModule(this);
}
It is generating ValidationComponent
but not DaggerNetComponent
Above are my module, components of my application. When I am compiling and building a application then I am getting below errors -
Error
Information:Gradle tasks [clean, :app:generateDebugSources, :app:mockableAndroidJar, :app:prepareDebugUnitTestDependencies, :app:generateDebugAndroidTestSources, :app:compileDebugSources, :app:compileDebugUnitTestSources, :app:compileDebugAndroidTestSources]
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\AppApplication.java
Error:(24, 48) error: cannot find symbol class DaggerNetComponent
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\login\AuthenticationActivity.java
Error:(35, 48) error: cannot find symbol class DaggerValidationComponent
Error:(39, 43) error: package com.icici.iciciappathon.databinding does not exist
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\checkout\PaymentActivity.java
Error:(28, 43) error: package com.icici.iciciappathon.databinding does not exist
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\dashboard\DashboardActivity.java
Error:(32, 43) error: package com.icici.iciciappathon.databinding does not exist
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\shopping\ScanBarcodeActivity.java
Error:(41, 43) error: package com.icici.iciciappathon.databinding does not exist
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\ui\GetStartedActivity.java
Error:(27, 43) error: package com.icici.iciciappathon.databinding does not exist
C:\Users\xyz\AndroidStudioProjects\ICICIAppathon\app\src\main\java\com\icici\iciciappathon\dagger\component\NetComponent.java
Error:(34, 10) error: com.mobsandgeeks.saripaar.Validator cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
com.icici.iciciappathon.login.AuthenticationActivity.validator
[injected field of type: com.mobsandgeeks.saripaar.Validator validator]
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
Information:BUILD FAILED
Information:Total time: 11.373 secs
Information:9 errors
Information:0 warnings
Information:See complete output in console
The general statement here is that Dagger doesn't generate classes when it encounters an error, usually when you're doing something impossible in your binding graph. That's the case here.
I agree with azizbekian that the problem is that you are trying to inject the Validator from within AuthenticationActivity, and telling NetComponent to try to do so without instructing it how to do so (in ValidationModule).
In the code you've posted, there isn't a reason for NetComponent to inject AuthenticationActivity; there's nothing for it to provide. So you can delete these two lines and be done:
// In NetComponent
void inject(AuthenticationActivity authenticationActivity);
// In AuthenticationActivity
((AppApplication) getApplication()).getmNetComponent().inject(this);
However, it's also possible that you've simply not shown us the NetComponent dependencies you need in AuthenticationActivity. In that case, you're going to need to combine the object graphs, either through subcomponents or component dependencies. You'll still need to delete the two lines listed above, because under no circumstance does NetComponent have the dependencies it needs to inject AuthenticationActivity.
Subcomponents
To do so with subcomponents, simply make a builder on NetComponent through which you get your ValidationActivity. You're welcome to provide a scope, but you don't necessarily need one, and I think it might be confusing to add that into the mix. At that point, your ValidationComponent will have access to all the bindings in your NetComponent AND all of the bindings listed in ValidationComponent. This is effectively identical to azizbekian's answer, though notably this is through subcomponents, not component dependencies. I'll talk about component dependencies in a moment.
// After removing the inject(AuthenticationActivity) call, add this to NetComponent
ValidatorComponent validatorComponent(ValidatorModule validatorModule);
// And call the implementation from AuthenticationActivity
((AppApplication) getApplication()).getmNetComponent()
.validatorModule(new ValidatorModule(this))
.inject();
You'll also need to switch ValidationComponent
from @Component
to @Subcomponent
, and remove the @Singleton
instance (which makes sense because you're creating a new one for every AuthenticationActivity instance Android creates.
Effectively, this turns NetComponent into a factory for ValidationComponent instances. Dagger generates the code for both at once, so ValidationComponent can access anything it needs from NetComponent automatically. However, this way it is impossible to generate code for each one separately, or to get a ValidationComponent without a NetComponent instance (except through including it in another component).
Component dependencies
Component dependencies work a little bit differently. They're freestanding components, so they can be generated separately and independently. Instead, you can pass in an interface (often but not necessarily another Dagger component like NetComponent), and every single no-argument method becomes an automatic provider into the other graph. This means, for example, that you could list specific dependencies available to ValidationComponent from NetComponent, add a dependencies={NetComponent.class}
to your ValidationComponent definition, and then change your DaggerValidationComponent builder to call .netComponent(((AppApplication getApplication()).getmNetComponent())
to hook the exact instances up. (Similarly, you could do so with any implementation of that interface, whether Dagger generates it or not; this can help with testing.) You'll also need to remove the use of @Singleton
, because Dagger would be very confused to have two separate components both claim to exist in singleton scope—one has to be created first, after all.
You haven't listed out the exact dependencies you're consuming out of NetComponent, so I don't have example changes I can show. However, for cases like this, I would recommend using subcomponents anyway; the bindings are more automatic, you likely won't benefit from the loose coupling you'd get from component dependencies, and you're closer to the design of Dagger's official Android support package so it's easier to migrate to that later.
这篇关于Dagger2未在Android中生成类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!