TheIcemanCometh
TheIcemanCometh

Reputation: 1056

Not getting singletons using Dagger

I am just getting started with Dagger in my current Android app, and I'm not sure how to achieve the functionality I'm looking for (I believe what I'm looking for is possible).

Basically, my situation is this. I have the following classes I want to have their instances/injections managed by Dagger. I also want some of these to be singletons, which are noted by (1):

Now, I can get Dagger to create these services and appropriately inject their dependencies just fine; the issue is that some classes have a dependency on more than one class and it appears through logging statements I'm getting new instances each time it gets injected.

Here is what I currently have for the above, including the Dagger module classes:

CryptoService.java

@Singleton
public class CryptoService {
    private final CipherFactory cipherFactory;

    @Inject
    CryptoService(CipherFactory cipherFactory) {
        this.cipherFactory = cipherFactory;
    }
    ...
}   

CryptoServiceModule.java

@Module(
        injects = CryptoService.class,
        complete = true,
        library = true
)
public class CryptoServiceModule {

    @Provides
    @Singleton
    CipherFactory provideCipher() {
        return new CipherFactory();
    }

}

SerializationService.java

@Singleton
public class SerializationService {

    private final ObjectMapper objectMapper;

    @Inject
    SerializationService(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
    ...
}

SerializationServiceModule.java

@Module(
        injects = SerializationService.class,
        library = true,
        complete = true
)
public class SerializationServiceModule {

    @Provides
    @Singleton
    ObjectMapper provideMapper() {
        return new ObjectMapper();
    }

}

PlayerApplicationService.java

public class PlayerApplicationService {

    private SerializationService serializationService;

    @Inject
    public PlayerApplicationService(SerializationService serializationService) {
        this.serializationService = serializationService;
    }
    ....
}

PlayerApplicationServiceModule.java

@Module(
        injects = PlayerApplicationService.class,
        includes = {
                SerializationServiceModule.class
        },
        complete = true,
        library = true
)
public class PlayerApplicationServiceModule {
}

PlayerRepository.java

@Singleton
public class PlayerRepository implements Repository<Player> {

    private final SerializationService serializationService;
    private final CryptoService cryptoService;

    @Inject
    public PlayerRepository(SerializationService serializationService, CryptoService cryptoService) {
        this.serializationService = serializationService;
        this.cryptoService = cryptoService;
    }
    ...
}

PlayerRepositoryModule.java

@Module(
        injects = PlayerRepository.class,
        includes = {
                SerializationServiceModule.class,
                CryptoServiceModule.class
        },
        complete = true,
        library = true
)
public class PlayerRepositoryModule {
}

What am I missing? As I mentioned above, all of this stuff works as is, it just looks like I'm getting multiple instances of some dependencies (SerializationService, for example, which is used by two classes) created where I only want/need one.

Upvotes: 0

Views: 338

Answers (1)

TheIcemanCometh
TheIcemanCometh

Reputation: 1056

Based on the comment by @Andyccs, I've consolidated everything into an application-level Module class and removed all other Module classes in the application:

PlayerApplicationModule.java

@Module(
        injects = {
                PlayerApplication.class,
                CryptoService.class,
                SerializationService.class,
                PlayerApplicationService.class
        },
        complete = true,
        library = true
)
public class PlayerApplicationModule {
    private PlayerApplication application;

    public PlayerApplicationModule(PlayerApplication application) {
        this.application = application;
    }

    @Provides
    @Singleton
    public Context provideApplicationContext() {
        return application;
    }

    @Provides
    @Singleton
    public CipherFactory provideCipherFactory() {
        return new CipherFactory();
    }

    @Provides
    @Singleton
    public ObjectMapper provideObjectMapper() {
        return new ObjectMapper();
    }

}

Everything is now working as expected.

Upvotes: 1

Related Questions