From dagger-discuss@:
I have a class that gets some dependencies from the object graph, and other dependencies from a caller at runtime.
public class ImageDownloader {
// Get these dependencies from the injector.
private final HttpClient httpClient;
private final ExecutorService executorService;
// Get these from the caller.
private final URL imageUrl;
private final ImageCallback callback;
...
}
I came up with a solution, where I define a Factory,
public class ImageDownloader {
...
public static class Factory {
private final HttpClient httpClient;
private final ExecutorService executorService;
@Inject
public Factory(HttpClient httpClient, ExecutorService executorService) {
this.httpclient = httpClient;
this.executorService = executorService;
}
public ImageDownloader create(URL imageUrl, ImageCallback callback) {
return new ImageDownloader(httpClient, executorService, iamgeUrl, callback);
}
}
...
}
Now, instead of injecting ImageDownloader
in the client's constructor, I simply inject ImageDownloader.Factory
and call its create()
method.
As you can see, that's quite verbose and long. It also has a bunch of duplication and boilerplate. There're some obstacles to annotating the fields themselves with @Inject
, so let's ignore this possibility for now.
The Square people have come up with an interesting solution, using providers. Define a Factory
interface,
public class ImageDownloader {
...
public interface Factory {
ImageDownloader create(URL imageUrl, ImageCallback callback);
}
}
and then provide it in a module,
public class ImageModule {
...
@Provides
public ImageModule.Factory provideImageModuleFactory(
final Provider<HttpClient> httpClientProvider,
final Provider<ExecutorService> executorServiceProvider) {
return new ImageDownloader.Factory() {
public ImageDownloader create(URL imageUrl, ImageCallback callback) {
return new ImageDownloader(httpClientProvider.get(), executorServiceProvider.get(),
imageUrl, callback);
}
}
...
}
(again, from dagger-discuss@).
My ImageDownloader
is a class that's injected by a class which is injected by another class which is injected by yet another class, ..., which is referenced in a @Module
. This all somehow* works, and all classes are found in build time. Now, to add a module, I have to explicitly let the object graph know about it.
I must be missing something - it's very easy to inject a new class, but very tedious to add a new module.
My question is: how is assisted injection done in practice? anyone has an example? how should I use ImageModule
, if at all?
* - "somehow" does indeed imply it's partly magic to me.