Назначение proxyProvide в кинжале 2 сгенерированный код
У меня есть этот кинжальный модуль. Я хочу понять сгенерированный код, поэтому я могу проверить, что моя конфигурация кинжала оптимальна.
@Module
public class TypefaceModule {
@Provides @Singleton @Named("Roboto Light")
static Typeface provideRobotoLight(AssetManager assets) {
return Typeface.createFromAsset(assets, "fonts/Roboto-Light.ttf");
}
}
Здесь сгенерированный код (Dagger 2.14.1):
public final class TypefaceModule_ProvideRobotoLightFactory implements Factory<Typeface> {
private final Provider<AssetManager> assetsProvider;
public TypefaceModule_ProvideRobotoLightFactory(Provider<AssetManager> assetsProvider) {
this.assetsProvider = assetsProvider;
}
@Override
public Typeface get() {
return Preconditions.checkNotNull(
TypefaceModule.provideRobotoLight(assetsProvider.get()),
"Cannot return null from a [email protected] @Provides method");
}
public static TypefaceModule_ProvideRobotoLightFactory create(
Provider<AssetManager> assetsProvider) {
return new TypefaceModule_ProvideRobotoLightFactory(assetsProvider);
}
public static Typeface proxyProvideRobotoLight(AssetManager assets) {
return Preconditions.checkNotNull(
TypefaceModule.provideRobotoLight(assets),
"Cannot return null from a [email protected] @Provides method");
}
}
Существуют две функции, которые выполняют почти одно и то же: метод экземпляра get()
и статический метод proxyProvideRobotoLight()
.
Почему Dagger сгенерировал две версии этого кода, которые статически называют метод provide()
модуля provide()
? Нельзя ли позвонить другому?
(Кстати, я понимаю, что мне больше не нужно связывать шрифты в моих активах приложения. Это не вопрос здесь.)
Ответы
Ответ 1
Во-первых: кинжал генерирует этот код досрочно, поэтому в модульной сборке вы получаете лучшую производительность сборки. Из-за этого мы не знаем, какой (или и тот, и другой) вам понадобится, поэтому мы генерируем как на всякий случай, так и предположим, что Proguard сможет отключить все, что не используется.
Итак, что же происходит на самом деле?
Первый (метод get()
) вызывается, когда привязка, которую этот factory представляет, запрашивается как Provider<T>
. Это может произойти либо напрямую, либо если привязка привязана, или несколько других сценариев.
Второй случай - это то, что мы называем вложением. Предположим, что у вас есть метод @Provides
в модуле, и у вас есть метод на @Component
, который возвращает этот тип. Самый идеальный код для генерации - это что-то вроде:
@Override
public YourBinding y() {
return YourModule.yourProvidesMethod();
}
Дело в том, что метод, предоставляющий метод, может быть недоступен из того же пакета, что и ваш компонент, поэтому мы генерируем этот метод "прокси", который дает Кинжал правильную доступность. Он также делает доступными все параметры для этого метода, стирая их до Object
, если необходимо. И если они действительно стираются (подумайте об этом как стирание стираемого типа), нам нужно затем вставить приведения в правильные типы внутри прокси-метода.
Реализация Provider.get()
не нуждается в этом, потому что там все типы должны быть доступны с помощью кода, который его вызывает.
Итак, чтобы подвести итог - мы хотим сгенерировать обе версии, надеюсь, вы должны использовать только один, и Proguard должен очистить другой.
Надеюсь, что это поможет!