Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dagger 2: Component depends on more than one scoped component

I'm pretty new to Dagger 2. I'm trying to implement it in my Android project. I've a Service which needs GoogleApiClient. I'm using Dagger to inject it in this service.

@FragmentScoped
@Component(dependencies = {NetComponent.class, RepositoryComponent.class})
public interface CustomServiceComponent {
    void inject(CustomService customService);
}

@Singleton
@Component(modules = {AppModule.class, NetModule.class})
public interface NetComponent {
    GoogleApiClient getGoogleApiClient();
}

@Singleton
@Component(modules = {AppModule.class, RepositoryModule.class})
public interface RepositoryComponent {
    DatabaseService getDatabaseService();
}

AppModule, NetModule, and RepositoryModule have methods marked @Singleton @Provides When I build my project I get this error:

The locationServiceComponent depends on more than one scoped component: @Singleton NetComponent @Singleton RepositoryComponent

I understand my LocationComponent cannot depend on two @Singleton scoped components but I need both of them in my service and both need to be @Singleton.

Is there any better alternative to do the same thing?

like image 922
crysis Avatar asked Dec 01 '16 12:12

crysis


1 Answers

Be aware that although you may have multiple components marked @Singleton their life cycles will follow those of the class where you retain the reference of the component.

This means if you initialise and retain your NetComponent and RepositoryComponent in an Activity it will follow the life cycle of that Activity and will not truly be an app singleton.

Hence, you probably won't need more than one @Singleton components in an Android app. Consider combining your two Singleton components into one component like this:

@Component(modules = {AppModule.class, NetModule.class, RepositoryModule.class})
@Singleton
public interface AppComponent {
    GoogleApiClient getGoogleApiClient();

    DatabaseService getDatabaseService();
}

Then make sure you retain this @Singleton component at Application level and make it available for use in dependent components that are initialised at the level of Fragment or Activity.

public class MyApp extends Application {

    private final AppComponent appComponent;

    @Override
    public void onCreate() {
        super.onCreate();
        appComponent = DaggerAppComponent.builder()
                           //modules if necessary
                           .build();
    }

    public AppComponent getAppComponent() {
        return appComponent;
    }                   
}

Note that as long as your @FragmentScoped don't have any dependent components themselves, you can still create as many of these as you like.

Note that even though one single component now injects GoogleApiClient and DatabaseService you still achieve separation of concerns because these are provided in separate Dagger 2 Modules.

like image 182
David Rawson Avatar answered Oct 14 '22 21:10

David Rawson