2016-04-25 9 views
8

Dagger 2を使い始めたばかりです。オンラインで何千ものガイドが異なる実装でガイドされていましたが、今はちょっと混乱しています。Dagger 2を使用したプレゼンターの注入

AppModule.java:

@Module 
public class AppModule { 

Application mApplication; 

public AppModule(Application application) { 
    mApplication = application; 
} 

@Provides 
@Singleton 
Application providesApplication() { 
    return mApplication; 
} 
} 

DataModule.java:

@Module 
public class DataModule { 

private static final String BASE_URL = "http://beta.fridgewizard.com:9001/api/"; 

@Provides 
@Singleton 
NetworkService provideNetworkService() { 
    return new NetworkService(BASE_URL); 
} 

@Provides 
@Singleton 
SharedPreferences provideSharedPreferences(Application app) { 
    return PreferenceManager.getDefaultSharedPreferences(app); 
} 
} 

PrefsModel.java:

@Module(includes = DataModule.class) 
public class PrefsModel { 

@Provides 
@Singleton 
QueryPreferences provideQuery(SharedPreferences prefs) { 
    return new QueryPreferences(prefs); 
} 
} 

AppComponent だから基本的にこれは私が現時点で書いたものです.java(私はQueryPreferencesオブジェクトを公開しています)このようにして正しい:

@Singleton 
@Component(modules = {AppModule.class, DataModule.class, PrefsModel.class}) 
public interface AppComponent { 

    void inject(HomeFragment homeFragment); 

    QueryPreferences preferences(); 
    NetworkService networkService(); 
} 

は、その後、私はFwApplication.java有する:

@Module 
public class PresenterModule { 

    @Provides 
    Presenter<FwView> provideHomePresenter(NetworkService networkService) { 
     return new HomePresenterImpl(networkService); 
    } 

    @Provides 
    Presenter<FwView> provideSearchPresenter(NetworkService networkService) { 
     return new SearchPresenterImpl(networkService); 
    } 

} 

そして次の成分(最後に私はプレゼンターのために別のモジュールを追加し

public class FwApplication extends Application { 

private static final String TAG = "FwApplication"; 

private NetworkService mNetworkService; 

private AppComponent mDataComponent; 

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

     buildComponentAndInject(); 
    } 

    public static AppComponent component(Context context) { 
     return ((FwApplication) context.getApplicationContext()).mDataComponent; 
    } 

    public void buildComponentAndInject() { 
     mDataComponent = DaggerComponentInitializer.init(this); 
    } 

    public static final class DaggerComponentInitializer { 
     public static AppComponent init(FwApplication app) { 
     return DaggerAppComponent.builder() 
       .appModule(new AppModule(app)) 
       .dataModule(new DataModule()) 
       .build(); 
    } 
    } 
} 

スコープ付きの依存関係をここに追加できないため、エラーが返されます)。

@Component(dependencies = AppComponent.class, modules = PresenterModule.class) 
public interface PresenterComponent { 

    void inject(HomePresenterImpl presenter); 
} 

だから、私は私がドキュメントをオンラインで読むため明らかにされていないいくつかの質問を持っている:それはAppComponentで定義されたシングルトンあるのNetworkServiceに依存するため

  • は、どのように私はプレゼンターコンポーネントでエラーを修正することができますか?

    HomeFragment:FIX -

  • 私は "新しいHomePresenter(NETWORKSERVICE)" とHomePresenterを実装する必要がありますが、今、私はDIが

EDIT定義されて使用する方法がわからないHomeFragmentを持っています.javaファイル:

public class HomeFragment extends Fragment { 

private static final String TAG = "FW.HomeFragment"; 


@Inject 
HomePresenterImpl mHomePresenter; 

public static HomeFragment newInstance() { 
    return new HomeFragment(); 
} 

@Override 
public void onCreate(@Nullable Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    FwApplication.component(getActivity()).inject(this); 
} 

は、その後、私はこのように、プレゼンターのコンストラクタを変更:

@Inject 
public HomePresenterImpl(NetworkService networkService) { 
    mNetworkService = networkService; 
    mInteractor = new InteractorImpl(mNetworkService); 
} 

NetworkServiceが自動的に挿入されます。

私は次のコードを上記1と同様に構成プレゼンターを必要とする私が持っているすべてのフラグメントのために呼び出す必要があるため、それはこのように正確である場合、私は思っていた

FwApplication.component(getActivity()).inject(this); 
+0

'プレゼンターコンポーネントでエラーを修正してください。 '*常に*エラーを含める –

+1

' '' getAactivity() '' '' 'onCreate()' ''で使用すると '' 'NullPointerException'''が生成されることがあります。 http://stackoverflow.com/a/6225044/1888738 – Bresiu

答えて

11

あなたがいます物を混ぜる。あなたの発表者を提供するには、次のようなものに切り替える必要があります。

できるだけコンストラクタインジェクションを使用してください。これは、インターフェイスの使用にこのコンストラクタinjecetionを提供し、が実装

Presenter<FwView> provideHomePresenter(HomePresenterImpl homePresenter) { 
    return homePresenter; 
} 

にあなたはどのコンストラクタを自分で呼び出す必要はありません。この方法をを依存するように物事がはるかに簡単

public class HomePresenterImpl { 

    @Inject 
    public HomePresenterImpl(NetworkService networkService) { 
     // ... 
    } 

} 

を行います。そして、実際に...プレゼンター

public class MyFragment extends Fragment { 

    @Inject 
    Presenter<FwView> mHomePresenter; 

    public void onCreate(Bundle xxx) { 
     // simplified. Add your modules/Singleton component 
     PresenterComponent component = DaggerPresenterComponent.create().inject(this); 
    } 
} 

あなたは物事を注入します。この道を注入します。これを注意深く読んで理解してください。これは

// DON'T 
@Provides 
Presenter<FwView> provideHomePresenter(NetworkService networkService) { /**/ } 

@Provides 
Presenter<FwView> provideSearchPresenter(NetworkService networkService) { /**/ } 

このしません作業(同じスコープ内で)あなたはまだ、同じモジュールから同じタイプの2人のプレゼンターを提供することはできません、あなたの主要な問題を修正します。同じ種類の2つのオブジェクトを提供することはできません。彼らは区別がつかない。これがあなたが行きたいと思う方法であることが確かであれば、@Namedのような@Qualifiersを見てください。

+0

ありがとうございました。私はあなたのアドバイスに従って、どのように修正したかを示す質問を編集しました。 (私はどのようにフラグメントにPresenterの注入を行ったのか分かりません) – user1341300

+2

あなたの 'return homePresenter;のための@David;あなたは' @ Binds'アノテーションを使うことができます。 https://google.github.io/dagger/faq.html#bindsとhttps://google.github.io/dagger/api/latest/dagger/Binds.html – TWiStErRob

+0

ありがとうございました!私は自分自身もこれに苦労していた。これは私の疑問の一部をクリアしました。ありがとうございました。 – taitasciore

4

@Injectアノテーションがコンストラクタで使用されている場合、Presenterを提供する必要はありません。クラスのコンストラクタで使用される@Injectアノテーションは、そのクラスを依存関係グラフの一部にします。したがって、必要に応じて注入することもできます。

一方、@Injectアノテーションをフィールドに追加するがコンストラクタに追加しない場合は、そのクラスを指定する必要があります。

関連する問題