Ошибка Android Dagger2: @javax.inject.Named("BaseUrl") java.lang.String связывается несколько раз

Я пробую кое-что с Dagger2, но все еще трудно понять..

Я хотел бы использовать 2 сервиса в 2 классах, SplashActivity и HomeActivity. Услуги зависят от NetModule, потому что я хотел бы повторно использовать модификацию и предоставляет okhttpclient.

Вот мой NetModule:

@Module
public class NetModule {
    @Provides
    Retrofit provideRetrofit(@Named("BaseUrl") String baseUrl, OkHttpClient okHttpClient) {
        return new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }

    @Provides
    HttpLoggingInterceptor provideHttpLoggingInterceptor() {
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        if (BuildConfig.DEBUG) {
            logging.setLevel(HttpLoggingInterceptor.Level.HEADERS);
        } else {
            logging.setLevel(HttpLoggingInterceptor.Level.NONE);
        }

        return logging;
    }

    @Provides
    OkHttpClient provideOkHttpClient(HttpLoggingInterceptor httpLoggingInterceptor, @Named("ConnectTimeoutMs") int connectTimeoutMs, @Named("ReadTimeoutMs") int readTimeoutMs) {
        return new OkHttpClient.Builder()
                .addInterceptor(httpLoggingInterceptor)
                .connectTimeout(connectTimeoutMs, TimeUnit.MILLISECONDS)
                .readTimeout(readTimeoutMs, TimeUnit.MILLISECONDS)
                .build();
    }
}

StaticDataModule и StatusModule, это 2 разных API, поэтому они используют NetModule:

@Module(includes = NetModule.class)
public class StaticDataModule {
    @Provides
    @Singleton
    StaticDataService provideStaticDataService(Retrofit retrofit) {
        return new RetrofitStaticDataService(retrofit);
    }

    @Provides
    @Named("BaseUrl")
    String provideBaseUrl() {
        return "http://url_static.com";
    }

    @Provides
    @Named("ConnectTimeoutMs")
    int provideConnectTimeoutMs() {
        return 5000;
    }

    @Provides
    @Named("ReadTimeoutMs")
    int provideReadTimeoutMs() {
        return 5000;
    }
}

@Module(includes = NetModule.class)
public class StatusModule {
    @Provides
    @Singleton
    StatusService provideStatusService(Retrofit retrofit) {
        return new RetrofitStatusService(retrofit);
    }

    @Provides
    @Named("BaseUrl")
    String provideBaseUrl() {
        return "http://url_status.com";
    }

    @Provides
    @Named("ConnectTimeoutMs")
    int provideConnectTimeoutMs() {
        return 5000;
    }

    @Provides
    @Named("ReadTimeoutMs")
    int provideReadTimeoutMs() {
        return 5000;
    }
}

И я строю их в этом компоненте:

@Singleton
@Component(modules = {AppModule.class, StaticDataModule.class, StatusModule.class})
public interface AppComponent {
    void inject(SplashActivity splashActivity);
    void inject(HomeActivity homeActivity);
}

Я получаю эту ошибку: @javax.inject.Named("BaseUrl") java.lang.String связывается несколько раз. Я понимаю свою ошибку, кинжал не знает, кто обеспечивает между StaticData baseUrl и Status baseUrl.

Я попытался сделать 2 компонента, StaticDataComponent и StatusComponent, но я не могу ввести оба в одной и той же деятельности.

Я пытался расширить NetModule в StaticDataModule и StatusModule, и дать параметры с помощью конструктора, но ошибка множественных границ была при модернизации.

Так что я не знаю, как повторно использовать NetModule с разными параметрами в 2 модулях, если у кого-то есть пример, он действительно должен мне помочь.

Спасибо!

2 ответа

Решение

Не включайте NetModule.class как зависимость от ваших модулей, просто включите их отдельно в компонент.

@Module(includes = NetModule.class)
public class StaticDataModule {

в

@Module
public class StaticDataModule {

А затем используйте как это:

@Component(modules = {
    NetModule.class, StaticDataModule.class
}) public interface FirstComponent {
  void inject(WhateverYouWantActivity activity);
}

@Component(modules = {
    NetModule.class, StatusModule.class
}) public interface FirstComponent {
  void inject(WhateverYouWantSecondActivity activity);
}

Если вам нужно внедрить в то же действие, вам лучше переделать свою архитектуру, но если вы все еще хотите сделать это, вы можете избавиться от метода ввода и добавить что-то вроде этого:

@Component(modules = { /* your modules */ }) public interface YourComponent {

  Retrofit getRetrofit();

  OkHttpClient getOkHttpClient();
}

И используйте его соответственно:

retrofit = yourComponentBuiltByDagger.getRetrofit();

Вместо:

@Inject Retrofit retrofit;

Наконец я нашел простое решение, моя архитектура была плохой. Теперь мне нужен только один модуль, и модернизация не предусмотрена, он встроен в реализацию StaticData и Status:

@Module
public class NetModule {
    @Provides
    HttpLoggingInterceptor provideHttpLoggingInterceptor() {
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        if (BuildConfig.DEBUG) {
            logging.setLevel(HttpLoggingInterceptor.Level.HEADERS);
        } else {
            logging.setLevel(HttpLoggingInterceptor.Level.NONE);
        }

        return logging;
    }

    @Provides
    OkHttpClient provideOkHttpClient(HttpLoggingInterceptor httpLoggingInterceptor) {
        return new OkHttpClient.Builder()
                .addInterceptor(httpLoggingInterceptor)
                .connectTimeout(5000, TimeUnit.MILLISECONDS)
                .readTimeout(5000, TimeUnit.MILLISECONDS)
                .build();
    }

    @Provides
    @Singleton
    StaticDataService provideStaticDataService(OkHttpClient okHttpClient) {
        return new RetrofitStaticDataService("http://url_1.com",okHttpClient);
    }

    @Provides
    @Singleton
    StatusService provideStatusService(OkHttpClient okHttpClient) {
        return new RetrofitStatusService("http://url_2.com",okHttpClient);
    }

}

@Singleton
@Component(modules = {AppModule.class, NetModule.class})
public interface AppComponent {
    void inject(SplashActivity splashActivity);
    void inject(HomeActivity homeActivity);
}

Объекты модификации находятся только в классе реализации модернизации, поэтому, если мне нужно изменить модификацию другой библиотеки, мне нужно просто изменить новый RetrofitStaticDataService() на новый AnotherStaticDataService().

Спасибо за помощь, Антон.

Другие вопросы по тегам