Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injection of GoogleApiClient

I want to inject to instances of Google api client in different parts of my project however I haven't manage to make it work.

@Provides @Named("geodata_api")
    @Singleton
    GoogleApiClient providesGoogleApiClient(Context context) {
            return new GoogleApiClient.Builder(context)
                    .addApi(Places.GEO_DATA_API)
                    .build();
        }

  @Provides @Named("location_api")
    @Singleton
    GoogleApiClient providesGoogleApiClient(Context context) {
        return new GoogleApiClient.Builder(providesContext())
                .addApi(LocationServices.API)
                .build();
    }
like image 853
george_mx Avatar asked Oct 18 '22 13:10

george_mx


1 Answers

The problem is that Dagger wouldn't be able to provide the callbacks, since the callbacks are implementation details, not dependencies -- and the callbacks are typically set before building the client (see option 2 below for more on callbacks).

One option would be to have Dagger provide the GoogleApiClient.Builder, and then your implementation must finish the chain by setting the callbacks and calling build():

@Provides
@Named("location_api")
GoogleApiClient.Builder provideLocationClient(Context context) {
    return new GoogleApiClient.Builder(context)
            .addApi(LocationServices.API);
}

@Provides
@Named("geodata_api")
GoogleApiClient.Builder provideGeodataClient(Context context) {
    return new GoogleApiClient.Builder(context)
            .addApi(Places.GEO_DATA_API);
}

Note the changes:

  1. @Named(..) is already a scope, so you should drop the @Singleton -- it's not needed.
  2. The two provider methods need to be named differently (provideLocationClient, provideGeodataClient)
  3. Instead of returning the GoogleApiClient, the module is returning a GoogleApiClient.Builder.

Now to use that dependency, you would inject the builder, and then attach your callbacks and build the client:

@Inject @NamedScope("location_api") GoogleApiClient.Builder mLocationClientBuilder;

...

mComponent.inject(this);
mClient = mLocationClientBuilder.<addCallbacks(...)>.build();
mClient.connect();

When mocking this builder using your unit test mocking framework, one thing you'll have to do is keep a reference to the callback, and invoke the onConnected(Bundle) callback method when connect() is called.


Another option is to provide the GoogleApiClient as you were, but then you have to remember to register your callbacks before connecting, and you have to remember to unregister those callbacks when you're done (to prevent a memory leak). See GoogleApiClient#registerConnectionCallbacks()

like image 177
Joe Avatar answered Oct 21 '22 06:10

Joe