0

I have a Dagger object graph that is able to produce instances of MyClass implicitly, as the constructor of MyClass is annotated with @Inject.

I also have a module that I plus onto my existing graph. My goal is for the plus'ed graph, and only for the plus'ed graph, to treat MyClass as a singleton and to always return the same instance.

How can I best achieve that with minimal boilerplate code, i.e. without

a) Constructing the instances myself in the plus'ed-on module by writing a @Provides @Singleton method, declaring all the dependencies of MyClass:

@Module public class Submodule {
  @Provides @Singleton MyClass provideMyClass(DepA depA, DepB depB) {
    return new MyClass(depA, depB);
  }
}

b) Extracting an interface from MyClass and again writing provider methods:

@Module public class Submodule {
  @Provides @Singleton IMyClass provideMyClass(MyClassImpl myClass) {
    return myClass;
  }
}

My concrete use case is that of an Android app, where an Activity instance depends on a presenter that should also be injected in fragments of the activity. Because several instances of the same Activity can exist, I can't declare MyClass a singleton globally.

I guess in the end, the question boils down to how one can write something like this, without the dependency cycle:

@Provides @Singleton public MyClass provideMyClass(MyClass m) { return m; }
Hannes Struß
  • 1,560
  • 2
  • 13
  • 20

1 Answers1

2

I don't think this is possible. You'll have to provide the @Singleton annotation somewhere.
Legal places for this are directly above the class declaration, or in a method annotated with @Provides.

With these two restrictions in mind, you've already proposed all possible solutions: The class declaration is not helpful since it should only be a singleton in the plus'ed graph, and the @Provides methods can only be implemented like you did.


The only thing I can think of that might be able to do this, is to supply your original ObjectGraph into your Submodule's constructor, and use ObjectGraph.get(MyClass.class) to return in your provideMyClass method. The con of course is that any overridden dependencies in your submodule are not used when creating the MyClass instance.

I think this method generates way too much overhead and introduces possible (future) bugs in comparison to your suggested methods.

nhaarman
  • 98,571
  • 55
  • 246
  • 278
  • One more idea I had that I'm bouncing off you, since you wrote the only reply :) I'm currently pondering whether it would be horrible or beautiful to have the plus'ed on module itself declare some dependencies (e.g. the presenter) and let the mother-graph instantiate or inject that module? – Hannes Struß Nov 10 '14 at 15:02
  • @HannesStruß I'm not sure what you mean. Perhaps you could start a new question where you can provide some example code? – nhaarman Nov 10 '14 at 19:33
  • something like this: https://gist.github.com/hannesstruss/827dad670971456adb8b But I'm not really convinced it's even worth consideration and thus its own question. I tried it and it works, but I think variant a) from my original question is probably better in terms of the principle of least surprise. – Hannes Struß Nov 11 '14 at 08:58