У меня есть класс, который получает некоторые зависимости от графа объектов и других зависимостей от вызывающего пользователя во время выполнения.
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;
...
}
Я придумал решение, где я определяю 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);
}
}
...
}
Теперь вместо ввода ImageDownloader
в конструкторе клиента я просто вставляю ImageDownloader.Factory
и вызываю его метод create()
.
Как вы можете видеть, это довольно многословно и долго. Он также имеет кучу дублирования и шаблона. Есть некоторые препятствия для аннотации самих полей с помощью @Inject
, поэтому пока не будем игнорировать эту возможность.
Люди Квадрата придумали интересное решение, используя поставщиков. Определите интерфейс Factory
,
public class ImageDownloader {
...
public interface Factory {
ImageDownloader create(URL imageUrl, ImageCallback callback);
}
}
а затем предоставить его в модуле,
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);
}
}
...
}
(опять же, из кинжала-обсуждения @).
My ImageDownloader
- это класс, который вводится классом, который вводится другим классом, который вводится еще одним классом..., на который ссылается в @Module
. Это все как-то * работает, и все классы находятся во время сборки. Теперь, чтобы добавить модуль, я должен явно сообщить об этом объекту.
Мне что-то не хватает - очень легко ввести новый класс, но очень утомительно добавить новый модуль.
Мой вопрос: как сделать инъекцию на практике? У кого-нибудь есть пример? как я должен использовать ImageModule
, если вообще?
* - "как-то" действительно означает, что это отчасти волшебство для меня.