簡體   English   中英

Dagger 2范圍和子組件

[英]Dagger 2 scope and subcomponents

我正在嘗試使我的應用程序更好,代碼更易於使用Dagger2我抓住了一般的想法,但仍然無法弄清楚范圍是如何管理Dagger2我注入匕首到我的項目(聽起來很有趣)。 我創建了ApplicationComonent組件,它在我的項目中完美運行。 這是我的代碼。

@Singleton
@Component(modules = {
        ApplicationModule.class,
        ThreadingModule.class,
        NetworkModule.class,
        DatabaseModule.class,
        ServiceModule.class,
        ParseModule.class,
        PreferencesSessionModule.class})

public interface ApplicationComponent {
    ActivityComponent activityComponent(ActivityModule activityModule);

    void inject(BaseActivity baseActivity);

    void inject(MainAppActivity mainAppActivity);

    void inject(MyApplication application);

    void inject(BaseFragment baseFragment);

    void inject(MyService service);

    void inject(RegistrationIntentService service);
}

我在MyApplication類中創建我的組件實例

private void initializeAndInjectComponent() {
        mApplicationComponent =
                DaggerApplicationComponent
                        .builder()
                        .threadingModule(new ThreadingModule(1))
                        .applicationModule(new ApplicationModule(this))
                        .networkModule(new NetworkModule(
                                MyService.API_SERVER_BASE_URL,
                                MyService.TIMEOUT))
                        .build();
        mApplicationComponent.inject(this);
    }

我可以獲得組件以便在我的Activities注入

    MyApplication application = MyApplication.get(this);
    application.getApplicationComponent().inject(this);

一切都很完美。

要添加每個方法以及模塊類,請使用@Singleton范圍進行注釋,所有模塊都與ApplicationComponent相關

現在我想要更好地依賴關系,我已經看到很多自定義范圍的例子,如@PerActivity@PerFragment 我有很多問題,但稍后會有這個問題。

所以我創建了ActivityComponent

@PerActivity
@Subcomponent(
        modules = {
                NetworkServiceModule.class,
                ActivityModule.class,
                PermissionModule.class
        })
public interface ActivityComponent {
    Activity activity();

    void inject(BaseActivity baseActivity);
}

所有模塊都是這樣的

@PerActivity
@Module
public class ActivityModule {
    private Activity mActivity;

    public ActivityModule(Activity activity) {
        this.mActivity = activity;
    }

    @Provides
    @PerActivity
    Activity provideActivity() {
        return this.mActivity;
    }
}

我的BaseActivity有以下依賴BaseActivity

// Dependencies from ApplicationComponent
    @Inject
    protected ApplicationSettingsManager mApplicationSettingsManager;
    @Inject
    protected ScheduledThreadPoolExecutor mPoolExecutor;
// Dependencies from ActivityComponent
    @Inject
    protected SpiceManager mSpiceManager;
    @Inject
    protected PermissionController mPermissionController;

在我的onCreate()方法中,我注入如下

    MyApplication application = MyApplication.get(this);
    application.getApplicationComponent().activityComponent(new ActivityModule(this)).inject(this);

在創建子組件ActivityComponent之前,它是

   MyApplication application = MyApplication.get(this);
        application.getApplicationComponent().inject(this);

現在我收到了一個錯誤

Error:(34, 10) error: com.octo.android.robospice.SpiceManager cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
BaseActivity.mSpiceManager
[injected field of type: com.octo.android.robospice.SpiceManager mSpiceManager]

我無法弄清楚問題在哪里,我錯過了什么。 我對dagger2中的范圍有疑問。

除了@Singleton所有東西都被Dagger 2忽略了,對嗎? 我不明白組件的生命是如何管理的? 我只有一個想法

  1. 當您使用@Singleton注釋時,dagger會在整個應用程序生命周期中存在的某個靜態池中創建對象,並且在銷毀JVM進程(dalvik VM,ART)實例時將被銷毀。

  2. 當你使用任何其他注釋只是為了讓你作為開發人員更好地維護代碼, @PerActivity@PerFragment只是自定義注釋而已。 如果你在Application類中放置@PerFragment組件,只要應用程序存在,它就會存在。 我對嗎 ?

  3. 所以我理解這一點,如果dagger找到@Singleton注釋,它將在第一次創建時添加對組件的靜態引用,並且在任何其他注釋的情況下,它將不保持對組件的引用。

對於上述問題的任何幫助,我將非常感激。

UPDATE

謝謝David Medenjak的答案,我對Dagger2有了更深入的Dagger2

我剛剛發現了問題,就我現在使用單獨的Activity組件而言,我忘記了ApplicationComponent兩行並將我的MainActivity inejction更改為ActivityComponent而不是ApplicationComponent ,所以肯定它無法解析子組件的依賴關系。

 void inject(BaseActivity baseActivity);

 void inject(MainAppActivity mainAppActivity);

現在一切都很完美,我喜歡Dagger2和分離的建築。

有點激進,但為了簡化事情: 所有范圍注釋都只是語法糖 - 包括@Singleton

范圍主要是提供編譯時檢查。 循環依賴關系,或者您可能錯過的事情的錯誤。 @Singleton就像任何其他范圍一樣,唯一的區別是它是一個已經存在的注釋,你不必自己創建它。 您可以使用@MySingleton代替。

[...] dagger正在一個靜態池中創建對象,該對象將在整個應用程序生命周期中存在

不,Dagger 什么都不做 你有組件對象。 這些組件包含由模塊創建的對象。 如果組件中的對象具有組件的范圍,則只會在該組件中創建一次。 如果您決定創建2個AppComponent對象,則每個@Singleton注釋對象將有2個對象,每個對象位於其組件中。 這就是您應該保留對組件的引用的原因。 我見過或使用的大多數實現因此將其AppComponent保留在其Application 如果你這樣做,你可以單身一樣使用它 - 它仍然只是一個POJO。

[...]你將@PerFragment組件放在Application類中,只要應用程序存在,它就會存在。

是。 如上段所述,它只是一個對象。 保留參考,保留對象。 扔掉它或創建一個新的對象(在此組件/范圍內定義)。 你應該盡管跟不上活動或片段范圍的部件的任何地方,除了分別在活動或片段,因為讓他們如在你的應用程序組件將最有可能導致內存泄漏。 (如果沒有,您可能不需要活動或片段范圍。)

如果dagger找到@Singleton注釋,它將在第一次創建時添加對組件的靜態引用,並且在任何其他注釋的情況下,它將不保持對組件的引用。

再一次,沒有。 沒什么是靜止的。 普通的舊java對象。 您可以將多個@Singleton組件與其自己的對象一起使用,但您可能不應該這樣做(盡管這是使得檢測可能/易於交換組件的原因。)


你提到的錯誤

沒有@Inject構造函數或@ Provide-或@ Produces-annotated方法,不能提供SpiceManager。

這意味着您嘗試注入對象的組件無法找到生成或提供SpiceManager任何方法。 確保您從AppComponent或其他地方提供,不遺漏任何注釋等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM