Библиотека почти похожа на приложение (когда дело доходит до Dagger). Да, у вас нет application
объекта, но он вам и не нужен.
Как потребитель вашей библиотеки, я ожидаю, что она будет простой в использовании, поэтому я вообще не хочу знать, что такое кинжал (и если вы используете его внутри компании).
Разрешите пользователям передавать Context
, когда они впервые обращаются к вашей библиотеке (например). Имейте DaggerInjector
(я думаю, ваш образец называет его оболочкой), который имеет статическую ссылку на ваш Component
интерфейс.
Пример (и как таковой, просто общий пример):
public class DaggerInjector {
private static YourComponent component;
private DaggerInjector() {
super();
}
public static YourComponent getComponent() {
return component;
}
public static YourComponent buildComponent(Context context) {
component = DaggerYourComponent
.builder()
.yourModule(new YourModule(context))
.build();
return component;
}
}
Ваш «модуль» может выглядеть так:
@Module
public class YourModule {
private Context context;
public YourModule(Context context) {
this.context = context;
}
@Provides
@Singleton
final Context providesContext() {
return context;
}
}
Чтобы использовать это:
Пусть ваши пользователи вызывают метод (или вы вызываете его в первый раз, если компонент равен нулю):
DaggerInjector.buildComponent(context);
Это обеспечит инициализацию компонента Dagger и генерацию кода. Поймите, что вызов buildComponent
- дорогостоящая задача (Dagger должен делать много!), Поэтому делайте это только один раз (если вам не нужно повторно инициализировать библиотеку с другими значениями, известными только во время выполнения).
Некоторые библиотеки просто запрашивают контекст при каждом вызове, так что это не исключено; вы могли бы затем инициализировать dagger при первом вызове (проверив, имеет ли getComponent () значение null в инжекторе).
После того, как ваш DaggerInjector.getComponent()
больше не равен нулю, теперь вы можете добавить @Inject
и соответствующий «вводимый» материал…
например: в YourModule
вы могли бы иметь:
@Provides
SomeObject providesSomeObject() {
return new SomeObject();
}
// THIS “Context” here is automatically injected by Dagger thanks to the above.
@Provides
@Singleton
SomeOtherObject providesSomeOtherObject(Context context) {
return new SomeOtherObject(context); //assume this one needs it
}
и в любом «вводимом» объекте (то есть в объекте, имеющем inject
метод в вашем компоненте…) вы можете:
public class AnObjectThatWantsToInjectStuff {
@Inject
SomeObject someObject;
@Inject
SomeOtherObject someOtherObject;
public AnObjectThatWantsToInjectStuff() {
super();
DaggerInjector.getComponent().inject(this);
// you can now use someObject and someOtherObject
}
}
Чтобы вышеперечисленное работало, вам нужен код YourComponent
(который является интерфейсом), например:
void inject(AnObjectThatWantsToInjectStuff object);
(в противном случае вызов DaggerInjector.getComponent().inject(this)
завершится ошибкой во время компиляции)
Заметьте, я никогда не передавал контекст YourInjectableContext
, Dagger уже знает, как его получить.
Будьте осторожны с утечками. Я рекомендую вам хранить context.getApplicationContext()
, а не просто Context
для всех / большинства случаев (если вам явно не нужен контекст Activity для надувания макетов / целей, контекст приложения, предоставляемый приложением-потребителем, - это все, что вам нужно).
person
Martin Marconcini
schedule
10.07.2017