0

I'm developing an Android app and want to use Dagger as my DI framework. But I don't know how to inject dependencies that use callbacks.

For example I want to get the location and I use GoogleApiClient for this:

public class LocationProvider implements ILocationProvider,
                                     GoogleApiClient.ConnectionCallbacks,
                                     GoogleApiClient.OnConnectionFailedListener {
    private GoogleApiClient googleApiClient;
    private ILocationRequester requester;

    public LocationProvider(@NonNull Context context, @NonNull ILocationRequester requester) {
        this.requester = requester;

        googleApiClient = new GoogleApiClient.Builder(context)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    }

    @Override
    public void beginGetLocation() {
        googleApiClient.connect();
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
        requester.locationFound(lastLocation);
    }

    @Override
    public void onConnectionSuspended(int i) {
        requester.locationFound(null);
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        requester.locationFound(null);
    }
}

In this case I'd like to inject the GoogleApiClient instance using Dagger to be able to mock it in my tests, but as it depends on this class I can't. The scenario is valid for any long running operation that uses callbacks even if I use another class to implement the callback.

Does anybody know a solution to this?

2 Answers2

0

you need to write a implementation class for the interface lets call it "ILocationRequesterImpl" and then write a method to provide an instance of that impl. for example in your module:

  @Provides
public ILocationRequester provideLocationRequester() {
    ILocationRequesterImpl lr=new ILocationRequesterImpl();
    return lr;
}

another way is to use constructor injection in ILocationRequesterImpl class like below:

public class ILocationRequesterImpl implements ILocationRequester {
@Inject
public ILocationRequesterImpl() {
} ... ...

and then this time in your module simply write:

  @Provides
public ILocationRequester provideLocationRequester(ILocationRequesterImpl lr) {
    return lr;
}
Amir Ziarati
  • 14,248
  • 11
  • 47
  • 52
0

You can take a look at Assisted Injection: https://dagger.dev/dev-guide/assisted-injection.html

Assisted injection is a dependency injection (DI) pattern that is used to construct an object where some parameters may be provided by the DI framework and others must be passed in at creation time (a.k.a “assisted”) by the user.

shubhamgarg1
  • 1,619
  • 1
  • 15
  • 20