I'm using Dagger 2 with retrofit2 library while using MVP. Everything went well till I tried to integrate another service (basically I tried to initialize another retrofit object to another service). I followed this answer but without any success.
Every time I'm getting an errors that each of my fragments and application classes don't seem to recognize the component classes.
error: cannot find symbol class DaggerApplicationComponent error: cannot find symbol class DaggerEpisodeComponent
Code
ApplicationComponent
@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
Retrofit exposeStreamingRetrofit();
Retrofit exposeRetrofit();
Context exposeContext();
AppPreferenceHelper exposePrefs();
}
Application Module
@Module
public class ApplicationModule
{
private String mBaseUrl;
private Context mContext;
private AppPreferenceHelper mPrefsHelper;
public ApplicationModule(Context context,String baseUrl)
{
mContext = context;
mBaseUrl = baseUrl;
mPrefsHelper = new AppPreferenceHelper(context, Consts.PREF_NAME);
}
@Singleton
@Provides
GsonConverterFactory provideGsonConverterFactory()
{
GsonConverterFactory gsonConverterFactory = GsonConverterFactory.create();
return gsonConverterFactory;
}
@Singleton
@Provides
@Named("ok-1")
OkHttpClient provideOkHttpClient()
{
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
return new OkHttpClient().newBuilder()
.connectTimeout(500, TimeUnit.MILLISECONDS)
.readTimeout(500,TimeUnit.MILLISECONDS)
.addInterceptor(logging)
.build();
}
@Singleton
@Provides
RxJava2CallAdapterFactory provideRxJava2CallAdapterFactory()
{
return RxJava2CallAdapterFactory.create();
}
@Provides
@Singleton
Retrofit provideRetrofit(@Named("ok-1") OkHttpClient client, GsonConverterFactory convectorFactory, RxJava2CallAdapterFactory adapterFactory)
{
return new Retrofit.Builder()
.baseUrl(mBaseUrl)
.addConverterFactory(convectorFactory)
.addCallAdapterFactory(adapterFactory)
.client(client)
.build();
}
@Provides
@Singleton
Retrofit provideStreamingRetrofit(@Named("ok-1") OkHttpClient client, GsonConverterFactory convectorFactory, RxJava2CallAdapterFactory adapterFactory) {
return new Retrofit.Builder()
.baseUrl(Consts.STREAMING_BASE_PATH)
.addConverterFactory(convectorFactory)
.addCallAdapterFactory(adapterFactory)
.client(client)
.build();
}
@Singleton
@Provides
Context provideContext()
{
return mContext;
}
@Singleton
@Provides
AppPreferenceHelper provideAppPreferenceHelper(){
return mPrefsHelper;
}
}
StreamingService
public interface StreamingService
{
@GET("search")
Observable<StreamingItems> getStreamingItems(@Query("keyword") String query);
}
Streaming Module @Module
public class StreamingModule
{
private StreamingView mView;
public StreamingModule(StreamingView view)
{
mView = view;
}
@PerFragment
@Provides
StreamingService provideStreamingService(Retrofit retrofit)
{
return retrofit.create(StreamingService.class);
}
@PerFragment
@Provides
StreamingView provideView()
{
return mView;
}
public void disposeView()
{
mView = null;
}
}
Streaming component
@PerFragment
@Component(modules = StreamingModule.class, dependencies = ApplicationComponent.class)
public interface StreamingComponent {
void inject(StreamingFragment streamingFragment);
}
Streaming Presenter
public class StreamingPresenter extends BasePresenter<StreamingView>
{
private long mMaxPagesOfTopSeries;
@Inject
protected StreamingService mApiService;
@Inject
protected Mapper mTopSeriesMapper;
@Inject
protected AppPreferenceHelper mPrefsHelper;
@Inject
public StreamingPresenter()
{
mMaxPagesOfTopSeries = 1;
}
}
The problem might be connected to the exposing another instance of Retrofit in the component application class, but I'm not sure.
Update 1
EpisodeModule
@PerFragment
@Component (modules = EpisodeModule.class, dependencies = ApplicationComponent.class)
public interface EpisodeComponent
{
void inject(EpisodeFragment episodeFragment);
}
After I created the streaming classes (service, presenter, module, component) I didn't change anything in other classes so I think the problem is somewhere in Application module/component or streaming classes but I'm not sure because I might change the retrofit object for the other fragments because I added a new instance of retrofit for streaming.
Yes, you can create two different Service instances.
Dagger automatically generates code that mimics the code you would otherwise have hand-written. Because the code is generated at compile time, it's traceable and more performant than other reflection-based solutions such as Guice. Note: Use Hilt for dependency injection on Android.
So, for Dagger to figure out which variable is to be provided with what, we have to explicitly specify the identifier for it. Thus, @Qualifier is used to distinguish between objects of the same type but with different instances .
You are right the problem is the second exposed instance of Retrofit in application module.The solution is to use dagger qualifiers. Just replace appropriate code blocks with:
Define retrofit provider with qualifier @Named("streaming")
in Application Module
@Provides
@Singleton
@Named("streaming")
Retrofit provideStreamingRetrofit(@Named("ok-1") OkHttpClient client, GsonConverterFactory convectorFactory, RxJava2CallAdapterFactory adapterFactory) {
return new Retrofit.Builder()
.baseUrl(Consts.STREAMING_BASE_PATH)
.addConverterFactory(convectorFactory)
.addCallAdapterFactory(adapterFactory)
.client(client)
.build();
}
Don't foreget to expose retrofit instance with exact same qualifier in Application Component
@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
@Named("streaming") Retrofit exposeStreamingRetrofit();
Retrofit exposeRetrofit();
Context exposeContext();
AppPreferenceHelper exposePrefs();
}
Whenever you need the streaming service retrofit instance - don't forget to set qualifier. Example in Streaming Module
@PerFragment
@Provides
StreamingService provideStreamingService(@Named("streaming") Retrofit retrofit) {
return retrofit.create(StreamingService.class);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With