0

This is driving me crazy. I can't seem to figure what is the problem with this.

Code:

public interface IMinutesCounter {
    void startTimer();

    void stopTimer();
}

and implementation:

public class MinutesMonitor implements IMinutesCounter {
    private ITimerCallback timerCallback;

    @Inject
    public MinutesMonitor(ITimerCallback timerCallback) {
        this.timerCallback = timerCallback;
    }

    void startTimer(){...}

    void stopTimer(){...}
}

CallAlarm implementing ITimerCallback

public class CallAlarm implements MinutesMonitor.ITimerCallback {

    @Inject
    public IMinutesCounter minutesMonitor;


    public CallAlarm (HealthService context) {
        this.minutesMonitor = minutesMonitor;
       ....
    }
}

As you can see, IMinutesCounter needs a MinutesMonitor.ITimerCallback.

What I want is - ** From the CallAlarm class (implementing MinutesMonitor.ITimerCallback)**inject myself (this) to instantiate the IMinutesCounter.

Dagger 2 part:

@Module
public class CallAlarmModule {

    IMinutesCounter.ITimerCallback timerCallBack;


    public CallAlarmModule(IMinutesCounter.ITimerCallback timerCallBack) {
        this.timerCallBack = timerCallBack;
    }

    @Provides
    public IMinutesCounter.ITimerCallback provideCallAlarm() {
        return timerCallBack;
    }
}

and:

@Component(modules = CallAlarmModule.class)
public interface CallAlarmComponent {
    void injectTimerCallback(IMinutesCounter.ITimerCallback service);
}

it gives me

error: IMinutesCounter cannot be provided without an @Provides- or @Produces-annotated method.

David Medenjak
  • 33,993
  • 14
  • 106
  • 134
Ofek Agmon
  • 5,040
  • 14
  • 57
  • 101

3 Answers3

0

This means that dagger does not know what a IMinutesCounter is or where to get one.

While dagger knows about MinutesMonitor and can construct it using constructor injection, you don't specify what to use for IMinutesCounter.

You can just remove the interface and just depend on MinutesMonitor, but I'm guessing that you actually want to use the interface and its implementation, for which you will have to provide the implementation, as the error suggests.

In your module add something like the following

@SomeScope // maybe add some scope
@Provides
public IMinutesCounter provideMinutesCounter(MinutesMonitor monitor) {
    return monitor;
}

This snippet makes use of constructor injection. It says to provide a IMinuteCounter I need a MinutesMonitor—its implementation. You then just return the implementation, and dagger will be able to use your implementation where the interface is requested.

@SomeScope // maybe add some scope
@Provides
public IMinutesCounter provideMinutesCounter(/* MM dependencies */) {
    return new MinutesMonitor(/* MM dependencies */);
}

The same could be done by just creating the object yourself, but I guess you see why just using constructor injection makes things easier.

David Medenjak
  • 33,993
  • 14
  • 106
  • 134
  • thanks for your answer. if I change the variable in CallAlarm to be MinutesMonitor like you said, I get same error but about ITimerCallback -"ITimerCallback cannot be provided without an Provides- or Produces-annotated method", and then, if I change in the MinutesMonitor the constructor to accept "CallAlarm" instead of "ITimerCallback" -> I get "dependency cycle" error – Ofek Agmon May 06 '16 at 13:59
  • @OfekAgmon yes, that's the same issue, again, with the interface not being found. You should probably provide your interfaces, and not rely on your implementation, as shown in the 2 code samples below. the cycle is a whole other issue, for which there is no _easy_ solution, you can read about it if you just search for `[dagger-2] cyclic` or `[dagger-2] cycle` here on SO – David Medenjak May 06 '16 at 14:07
  • I added the first snippet you posted, and left the other code as is - I still have the same error, cant provide IMinutesCounter – Ofek Agmon May 06 '16 at 14:13
  • @DavidMedejak, isn't this case like this one? http://stackoverflow.com/questions/37052261/using-dagger-2-to-inject-into-service ? your answer over there worked great and this issue looks the same, having an object that needs to instantiate another object with himself as a parameter. though, when I tried to apply the code from the other answer, it gave me the error – Ofek Agmon May 06 '16 at 14:28
0

I think you can easily fix this with the following additional line:

@Module
public class CallAlarmModule {
    @Provides
    public IMinutesCounter minutesCounter(MinutesCounter minutesCounter) {
        return minutesCounter;
    }

    ...
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • Also, your `CallAlarm` doesn't actually receive a `minutesMonitor` even though it should in its constructor – EpicPandaForce May 06 '16 at 14:37
  • I added it, now it says "cant provide ITimerCallback" – Ofek Agmon May 06 '16 at 14:43
  • please look at the answer here - http://stackoverflow.com/questions/37052261/using-dagger-2-to-inject-into-service. its about injecting a service from the service's OnCreate (this) into the class he is dependent on. isn't this the same? – Ofek Agmon May 06 '16 at 14:49
  • ....I can't really tell, the code that makes your question not work is not included here. – EpicPandaForce May 06 '16 at 15:32
  • please see my new question here, see if you know what's the problem.http://stackoverflow.com/questions/37075951/dagger-2-cant-figure-out-how-to-inject-myself-this-into-class-without-depende – Ofek Agmon May 06 '16 at 15:35
0
@Inject
public IMinutesCounter minutesMonitor;

change to

@Inject
public MinutesCounter minutesMonitor;

cause your interface can't be injected.

Tushar
  • 85,780
  • 21
  • 159
  • 179