Dagger2, обеспечивающий модифицированные экземпляры с разными API одновременно

#android #retrofit #mvp #dagger-2

#Android #модернизация #mvp #dagger-2

Вопрос:

В моем проекте я использую Retrofit и пытаюсь использовать Dagger для внедрения зависимостей. У меня также есть 2 модифицированных сервиса с разными API. Мне нужно одновременно использовать 2 разных API с разными базовыми ссылками. Я застрял здесь и не знаю, что делать дальше.

Мой ApplicationModule:

 @Module
public class ApplicationModule {

private String FIRST_API_URL = "https://first-api.com";
private String SECOND_API_URL = "https://second-api.com";

private String mBaseUrl;
private Context mContext;

public ApplicationModule(Context context) {
    mContext = context;
}

@Singleton
@Provides
GsonConverterFactory provideGsonConverterFactory() {
    return GsonConverterFactory.create();
}

@Singleton
@Provides
@Named("ok-1")
OkHttpClient provideOkHttpClient1() {
    return new OkHttpClient.Builder()
            .connectTimeout(20, TimeUnit.SECONDS)
            .readTimeout(20, TimeUnit.SECONDS)
            .build();
}

@Singleton
@Provides
@Named("ok-2")
OkHttpClient provideOkHttpClient2() {
    return new OkHttpClient.Builder()
            .connectTimeout(60, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .build();
}

@Singleton
@Provides
RxJavaCallAdapterFactory provideRxJavaCallAdapterFactory() {
    return RxJavaCallAdapterFactory.create();
}

@Singleton
@Provides
@FirstApi
Retrofit provideRetrofit(@Named("ok-1") OkHttpClient client, GsonConverterFactory converterFactory, RxJavaCallAdapterFactory adapterFactory) {
    return new Retrofit.Builder()
            .baseUrl(FIRST_API_URL)
            .addConverterFactory(converterFactory)
            .addCallAdapterFactory(adapterFactory)
            .client(client)
            .build();
}

@Singleton
@Provides
@SecondApi
Retrofit provideRetrofit2(@Named("ok-1") OkHttpClient client, GsonConverterFactory converterFactory, RxJavaCallAdapterFactory adapterFactory) {
    return new Retrofit.Builder()
            .baseUrl(SECOND_API_URL)
            .addConverterFactory(converterFactory)
            .addCallAdapterFactory(adapterFactory)
            .client(client)
            .build();
}

@Provides
@Singleton
Context provideContext() {
    return mContext;
}
}
  

Мое приложение:

 public class MyApplication extends Application {

private ApplicationComponent mApplicationComponent;

@Override
public void onCreate() {
    super.onCreate();
    initializeApplicationComponent();
}

private void initializeApplicationComponent() {
    mApplicationComponent = DaggerApplicationComponent
            .builder()
            .applicationModule(new ApplicationModule(this, Constant.BASE_URL))   // I think here needs to do something to use different URLs
            .build();
}

public ApplicationComponent getApplicationComponent() {
    return mApplicationComponent;
}

@Override
public void onTerminate() {
    super.onTerminate();
}
}
  

Вот как я разрешаю зависимости в своем фрагменте.

     protected void resolveDependency() {
    DaggerSerialComponent.builder()
            .applicationComponent(getApplicationComponent())
            .contactModule(new ContactModule(this))
            .build().inject(this);
}
  

Проблема в том, что мне нужно выполнить инъекцию с 2 API во фрагменте, чтобы получить данные из этих API.

ОБНОВЛЕНО: я создал аннотации:

 @Qualifier
@Retention(RUNTIME)
public @interface FirstApi{}

@Qualifier
@Retention(RUNTIME)
public @interface SecondApi{}
  

Мой контактный модуль:

 @Module
public class ContactModule {

private ContactView mContactView;

public ContactModule(ContactView contactView) {
    mContactView = contactView;

}

@PerActivity
@Provides
FirstContactService provideFirstContactService(@FirstApi Retrofit retrofit) {
    return retrofit.create(FirstContactService.class);
}

@PerActivity
@Provides
SecondContactService provideSecondContactService(@SecondApi Retrofit retrofit) {
    return retrofit.create(SecondContactService.class);
}

@PerActivity
@Provides
ContactView provideContactView() {
    return mContactView;
}
}
  

Я всегда получаю сообщение об ошибке «retrofit2.retrofit не может быть предоставлен без и @Provides или @Products-аннотированный метод»

ApplicationComponent

 @Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {

    Retrofit exposeRetrofit();

    Context exposeContext();
}
  

Комментарии:

1. куда вводится ваша модификация? Во фрагменте должен быть внедренный модифицированный экземпляр, и вы, вероятно, тоже можете его назвать

Ответ №1:

Вы просто используете @Inject аннотацию вместе с @Named() аннотацией, вот так:

 @Inject @Named("provideRetrofit") Retrofit mRetrofit;
@Inject @Named("provideRetrofit2") Retrofit mRetrofit2;
  

Или вы могли бы даже внедрить модифицированные сервисы напрямую:

 @Provides @Singleton
public CustomService provideCustomService(@Named("provideRetrofit") Retrofit retrofit) {
    return retrofit.create(CustomService.class);
}
  

Комментарии:

1. Когда я добавляю именованную аннотацию в rertofit, я получаю сообщение об ошибке «retrofit2. Модификация не может быть предоставлена без конструктора @Inject или из метода с аннотацией Provides. модифицированный2. Модификация предоставляется в com.myapp.dependencies.component . ApplicationComponent.exposeRetrofit() »

2. @STK90 Вы пробовали очищать и перестраивать свой проект? Зависимости не будут обновляться до тех пор, пока Dagger не сгенерирует ваш объектный граф, чего не произойдет, пока не будет выполнена новая сборка.

Ответ №2:

добавьте аннотацию @Named к предоставленным вами модифицированным экземплярам, как показано ниже:

 @Named("retrofit_one")
Retrofit provideRetrofit(@Named("ok-1") OkHttpClient client, GsonConverterFactory converterFactory, RxJavaCallAdapterFactory adapterFactory) {
return new Retrofit.Builder()
.baseUrl(FIRST_API_URL) 
.addConverterFactory(converterFactory) 
.addCallAdapterFactory(adapterFactory) 
.client(client) 
.build();
 }



@Named("retrofit_two")
    Retrofit provideRetrofit(@Named("ok-1") OkHttpClient client, GsonConverterFactory converterFactory, RxJavaCallAdapterFactory adapterFactory) {
    return new Retrofit.Builder()
    .baseUrl(SECOND_API_URL) 
    .addConverterFactory(converterFactory) 
    .addCallAdapterFactory(adapterFactory) 
    .client(client) 
    .build();
     }
  

а затем, где бы вам ни понадобилось, введите два экземпляра, например:

 @Inject @Named("retrofit_one") Retrofit mRetrofitOne;   
@Inject @Named("retrofit_two") Retrofit mRetrofitTwo;