1

I am using Dagger-2 (ver: 2.7) and AutoFactory (ver: 1.0-beta3). I am facing a peculiar issue.

I have a a class MyRequest who's ctor takes 2 parameters as:

  1. ConnectivityManager conmgr
  2. int somevalue

I created the ctor as

@Autofactory
public MyRequest(@Provider ConnectivityManager conmgr, int somevalue){
//
}

I have a module containing the following

@Provides
@SystemScope
public final ConnectivityManager provideConnectivityManager(App app) {
return (ConnectivityManager)       
app.getSystemService(Context.CONNECTIVITY_SERVICE);
}

In the same module I do the following

@Provides
@SystemScope
public final MyRequestFactory providesMyRequestFactory(ConnectivityManager connectivityManager {
    return new MyRequestFactory(connectivityManager);
}

I am getting build error incompatible types: ConnectivityManager cannot be converted to Provider < ConnectivityManager >.

Any idea how to solve this ?

shyguy
  • 301
  • 3
  • 8

1 Answers1

3

As in the AutoFactory example, if your constructor takes a Foo, your AutoFactory's generated constructor will take a Provider<Foo> instead. This is so your factory will request a new Foo (or ConnectivityManager) once for each call to get without necessarily sharing instances between them.

It may be the case that you want Foo or ConnectivityManager to be the same instance for all instances of the created object (MyRequest here), but that's for you and Dagger to dictate, not AutoFactory. Consequently, AutoFactory will always generate code that takes Providers, whether you use them that way or not.

Luckily, the fix is very easy: Dagger can inject a Provider<ConnectivityManager> just as easily as it can inject a ConnectivityManager (as it can for any binding), so you can just change your @Provides method like so...

@Provides
@SystemScope
public final MyRequestFactory providesMyRequestFactory(
        Provider<ConnectivityManager> connectivityManagerProvider {
    return new MyRequestFactory(connectivityManagerProvider);
}

...but because your generated factory will have an @Inject annotation, you would probably be better off deleting the @Provides method entirely and letting Dagger use that constructor for MyRequestFactory injections. Though you'll lose the @SystemScope scope annotation from the @Provides method, that's no problem: With the Provider<ConnectivityManager> injection above, you don't have to worry about the lifecycle of the generated factory, so you can fall back to a default unscoped provision.

Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • Thanks for the good explanation. And for good reasons on why I don't need "@Provides" for "MyRequest". However would you be able to provide an insight how Dagger-2 will inject Provider even though I am providing just ConnectivityManger using "@Provides ConnectivityManager" in my module (and not Provider < ConnectivityManager> – shyguy Oct 03 '16 at 04:02
  • @shyguy You're welcome! And you probably will need @Provides for MyRequest, but not for MyRequestFactory. You can see the ["Bindings in the Graph" section of the Dagger 2 User Guide](http://google.github.io/dagger/users-guide.html#bindings-in-the-graph) for details, but suffice to say that Dagger will handle requests for `Provider`, `Lazy`, or even `Provider>` for any `T` you make available through a `@Provides` method or otherwise. – Jeff Bowman Oct 03 '16 at 04:10
  • Sorry for the typo I meant MyRequestFactory only. I will definitely go through the link suggested by you. Thanks again @Jeff Bowman – shyguy Oct 03 '16 at 05:01