Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dagger: What if I *WANT* a new instance every time?

Interesting how difficult this answer is to find.

I've been using Dagger - Android for a while now and have my entire dependency graph set up. I'm using scopes, qualifiers, all that good stuff. I'm not a Dagger newbie anymore, but suffice to say I've been using it in a pretty standard way in my Android setup and everything has been going great.

For the first time, I'm realizing that I'd like to request new instances of a certain class in my graph myself, manually, and I want it to be a new instance every time.

What's the best way to go about doing that? I'm wondering if there's a way to leverage a non-@Singleton/non-scoped provider and call some sort of create() method myself, or if it's best to create a factory myself and make that factory a singleton/scoped instance and use my factory to get the new instance(s) when I need them? [I should mention this class will definitely not have an empty constructor so will need injected instances of other classes defined in my injection graph.]

(Also, it would probably help the most if answers were in the context of Android; i.e. I'm in, say, a ViewModel and need a new instance of some class defined in one of my Modules.)

like image 226
Codepunk Avatar asked Dec 13 '18 14:12

Codepunk


People also ask

What does @inject do Dagger?

Use @Inject to annotate the constructor that Dagger should use to create instances of a class. When a new instance is requested, Dagger will obtain the required parameters values and invoke this constructor. class Thermosiphon implements Pump { private final Heater heater; @Inject Thermosiphon(Heater heater) { this.

What is @singleton in Dagger?

The @Singleton annotation is used to declare to Dagger that the provided object is to be only initialized only once during the entire lifecycle of the Component which uses that Module.

What is @component in Dagger?

Now Component in a Dagger works by creating a graph of all the dependencies in the project so that it can find out where it should get those dependencies when they are needed. In order to implement this, an interface needs to be created and should be annotated with @Component.

How do you inject value at runtime in Dagger?

Inject values at runtime with UI in Dagger2:pureMathModule("Book Name") . build() . inject(this); The difference between DaggerComponent create() and in build() is - create() works when no runtime argument is passed into the constructor, else we use build() method.


1 Answers

Dagger will provide you a new instance as long as you don't scope the dependency.

To get a new instance of a dependency manually, you can inject Provider of it instead and use its get() method, it'll give you a new instance every time you call it.

Module part doesn't really change:

@Module
class AppModule {

    @Provides
    fun provideSomeObject(): SomeObject = SomeObject()
}

And in your class

class SomeClass {
    // We don't inject the object anymore
    // @Inject lateinit var myObject : SomeObject

    // We'll inject it's provider
    @Inject lateinit var myObject : Provider<SomeObject>

    fun someMethod(){
        // Here, instance1 and instance2 are NOT same objects
        val instance1 = myObject.get()
        val instance2 = myObject.get()
    }
}

You can read more here.

like image 99
Mel Avatar answered Oct 17 '22 17:10

Mel