2016-04-25 61 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:

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

最後,我加入了對主持人的另一個模塊:

@Module 
public class PresenterModule { 

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

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

} 

而下面的組件(這會返回錯誤,因爲我不能在這裏添加範圍相關性):

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

    void inject(HomePresenterImpl presenter); 
} 

所以,我認爲是不明確的,我閱讀文檔在線幾個問題:

  • 我怎樣才能修復該錯誤演示組件,因爲這取決於網絡服務是在AppComponent定義的單?
  • 我有應該實現與HomePresenter 「新HomePresenter(network服務)」,但現在我不知道如何使用DI定義

編輯HomeFragment - FIX:

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被自動注入。

我在想,如果是這樣,正確的,因爲我要呼籲每一個片段我有一個需要以同樣的方式構成的一個下面的代碼上面的演示:

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

'固定在演示component'錯誤請*總是*包括錯誤 –

+1

'''getAactivity()'''中使用'''的onCreate()'''可產生'''NullPointerException'''。 http://stackoverflow.com/a/6225044/1888738 – Bresiu

回答

11

你是把東西混合起來。要提供您的演示者,您應該切換到以下內容:

如果可能,請使用構造函數注入。這將使事情變得更加簡單

public class HomePresenterImpl { 

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

} 

提供的接口使用此構造injecetion和在實施

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

這樣,您就不必自己調用任何構造函數依賴。而實際上注入演示...

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

這樣,您將注入的東西。請仔細閱讀並理解它。這將解決您的大問題,你仍然不能提供2名主持人相同類型的從同一模塊(在相同的範圍內)

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

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

不會工作。你不能提供2個同類的對象。它們無法區分。看看@Qualifiers@Named如果你確定這是你想要的方式。

+0

非常感謝你的回答,我編輯了這個問題,以顯示我如何解決你的意見。 (我不知道我是如何在片段中完成Presenter注入的) – user1341300

+2

@David爲您的'返回homePresenter';'您可以使用'@ 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註釋添加到字段,而不添加到構造函數,則必須提供該類。