2016-09-16 6 views
2

私はDagger2といくつかのことをしようとしているが、依然として困難を理解すること。..アンドロイドDagger2エラー:javax.inject.Named @(「BASEURL」)java.lang.Stringではバインドされている複数回

私はしたいと思いますSplashActivityとHomeActivityの2つのクラスで2つのサービスを使用します。 サービスはNetModuleに依存しています。これは、再利用retrofitと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、それは彼らがNetModule使用して2貴様APIです:

@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の間に誰が提供しているのか知りません。

StaticDataComponentとStatusComponentの2つのコンポーネントを作成しようとしましたが、同じアクティビティで両方を注入できません。

StaticDataModuleとStatusModuleでNetModuleを拡張しようとしましたが、コンストラクタでパラメータを指定しましたが、複数の境界エラーがretrofitで提供されました。

私は2つのモジュールのdifferentsパラメータでNetModuleを再利用する方法を知りません。

ありがとうございます!

+0

最も簡単なことは、次のようにすることができます:StatusBaseUrlとStaticBaseUrlに名前を変更する –

+0

しかし、NetModule for baseUrlには何が必要ですか?私は@Named( "Something")を書く必要がありますか? – Lyofen

+0

または、同じ名前を使用しますが、NetModuleを依存関係として含めないでください。 2番目のコンポーネント(NetModule +静的モジュール)の1つのコンポーネント(NetModule +ステータスモジュール)に使用 –

答えて

1

モジュールに依存するものとしてNetModule.classを含めないでください。構成要素にNetModule.classを別々に含めてください。

@Module 
public class StaticDataModule { 

@Module(includes = NetModule.class) 
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; 
+0

Ok thx私はそれを行います。たぶん私は、以前のanwserのように、異なる名前の独自のprovideRetrofitでStaticDataModuleとStatusModuleを作成しようとすることができます。唯一の問題は、私は、retrofitを使っている各apiサービスに対してprovideRetrofitを再定義する必要があります。 – Lyofen

+0

あなたは1つのアクティビティに2つのレトロフィットを注入しますか? –

+0

私は、改造をアクティビティにリンクするのを避けたいのですが、別のライブラリで改造を変更したいのであれば、それをモジュールでのみ変更したいと思います。 – Lyofen

2

を最終的に私は簡単な解決策を見つけ、自分のアーキテクチャが悪かったです。今、私は一つだけのモジュールを必要とし、改造が提供されていない、彼はStaticDataとステータスの実装の内側に構築さ:

@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); 
} 

レトロフィットオブジェクトのみを換装実装クラスであるので、私は別のライブラリで改造を変更する必要がある場合、私はちょうど持っています新しいAnotherStaticDataService()によって新しいRetrofitStaticDataService()を変更します。

ありがとうございました。

関連する問題