Reputation: 4530
I want to know how to inject Presenter in activity using code Following are details
Following is error message:
Error:(12, 46) error: cannot find symbol class DaggerCategoryPresenterComponent
Error:(9, 46) error: cannot find symbol class DaggerNetComponent
Error:(18, 10) error: [Dagger/MissingBinding] com.headytest.android.category_listing.CategoryContract.CategoryPresenter cannot be provided without an @Provides-annotated method.
com.headytest.android.category_listing.CategoryContract.CategoryPresenter is injected at
com.headytest.android.MainActivity.categoryPresenter
com.headytest.android.MainActivity is injected at
com.headytest.android.dagger_component.NetComponent.inject(com.headytest.android.MainActivity)
Following are modules
@Module
public class NetworkModule {
String baseURL;
public NetworkModule(String baseURL) {
this.baseURL = baseURL;
}
@Provides
@Singleton
Cache provideHttpCache(Application application) {
int cacheSize = 10 * 1024 * 1024;
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) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.cache(cache);
client.addInterceptor(interceptor);
return client.build();
}
@Provides
@Singleton
Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
try {
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(baseURL)
.client(okHttpClient)
.build();
} catch (Exception e) {
e.printStackTrace();
return new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(Constants.BASE_URL)
.client(okHttpClient)
.build();
}
}
}
ApplicationModule
@Module
public class ApplicationModule {
Application application;
public ApplicationModule(Application application) {
this.application = application;
}
@Provides
@Singleton
Application providesApplication() {
return application;
}
}
CategoryContractModule
@Module
public class CategoryContractModule {
public CategoryContractModule() {
}
@Provides
@AScope
CategoryContract.CategoryPresenter providesCategoryPresenter(CategoryPresenterImpl categoryPresenter) {
return (CategoryContract.CategoryPresenter)categoryPresenter;
}
}
Following are components:
@Singleton
@Component(modules = {ApplicationModule.class, NetworkModule.class})
public interface NetComponent {
void inject(MainActivity activity);
}
CategoryPresenterComponent
:
@AScope
@Component(dependencies = NetComponent.class, modules =
{CategoryContractModule.class})
public interface CategoryPresenterComponent {
void inject(MainActivity activity);
}
AScope
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface AScope {
}
Following is the code in MainActivity
:
@Inject
CategoryPresenter categoryPresenter;
@Inject
Retrofit retrofit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerCategoryPresenterComponent.builder()
.categoryContractModule(new CategoryContractModule())
.netComponent(((App) getApplicationContext()).getNetComponent())
.build()
.inject(this);
}
CategoryPresenterImpl
public class CategoryPresenterImpl implements CategoryContract.CategoryPresenter {
@Inject
public CategoryPresenterImpl() {
}
@Override
public void onStart() {
}
@Override
public void onStop() {
}
@Override
public void getCategoryLiast() {
}
}
Upvotes: 2
Views: 966
Reputation: 62179
I assume current error will be easy to fix, because it very much looks like this issue.
You've instructed Dagger how to provide @AScope CategoryContract.CategoryPresenter
but in activity you request Dagger to inject CategoryContract.CategoryPresenter
. Dagger is confused at this point, because those two things do not match.
What you have to do, is simply add @AScope
to categoryPresenter
:
@Inject
@AScope
CategoryPresenter categoryPresenter;
I've checked out your project. The problem was in NetComponent.java
:
@Singleton
@Component(modules = {ApplicationModule.class, NetworkModule.class})
public interface NetComponent {
void inject(MainActivity activity);
}
The issue is in line void inject(MainActivity activity)
. Why is this an issue? Because by the time you construct NetComponent
in App
, dagger analyzes MainActivity
for @Inject
annotated field and sees CategoryPresenter
. This means, that at this point Dagger should find appropriate provider/binder method in order to be able to inject MainActivity
as declared inside this interface.
But it cannot find such a provider/binder method, because it is declared in an another component - CategoryPresenterComponent
and this component (NetComponent
) is not connected with CategoryPresenterComponent
anyhow (subcomponents or component dependencies), thus bindings are not exposed.
Simply removing that line will make your build successful:
@Singleton
@Component(modules = {ApplicationModule.class, NetworkModule.class})
public interface NetComponent {
}
For resolving "Error:cannot access Nullable" refer to this thread, which suggest applying compile 'com.google.code.findbugs:jsr305:3.0.2'
to your gradle file.
After doing this you'll overcome that error message and will stumble on retrofit2.Retrofit cannot be provided without an @Inject constructor or an @Provides-annotated method
, which has the same symptoms as CategoryPresenter
had.
To overcome this issue you have to add a Retrofit
provider method inside NetComponent
(or to remove @Inject Retrofit retrofit
from activity):
@Singleton
@Component(modules = {ApplicationModule.class, NetworkModule.class})
public interface NetComponent {
Retrofit providesRetrofit();
}
After doing this you'll be able to run the app, but you'll end up in a NPE in MainActivity
, because of this line:
.categoryContractModule(new CategoryContractModule(retrofit.create(HeadyAPI.class)))
You are referring to retrofit
object, which is not yet initialized.
Long story short, your initial question has mutated a couple of times and in fact you had a few problems in your code. Still you have a problem there, because you are trying to use retrofit
in order to construct a component, that was supposed to inject the retrofit
for you.
Upvotes: 1