Я пытаюсь улучшить свое приложение и код с большей поддержкой, используя Dagger2
. Я понял общую идею, но до сих пор не могу понять, как управлять областями с помощью Dagger2
Я вложил кинжал в свой проект (звучит смешно).
Я создал компонент ApplicationComonent
, и он отлично работает в моем проекте.
Вот мой код.
@Singleton
@Component(modules = {
ApplicationModule.class,
ThreadingModule.class,
NetworkModule.class,
DatabaseModule.class,
ServiceModule.class,
ParseModule.class,
PreferencesSessionModule.class})
public interface ApplicationComponent {
ActivityComponent activityComponent(ActivityModule activityModule);
void inject(BaseActivity baseActivity);
void inject(MainAppActivity mainAppActivity);
void inject(MyApplication application);
void inject(BaseFragment baseFragment);
void inject(MyService service);
void inject(RegistrationIntentService service);
}
Я создаю экземпляр компонента в классе MyApplication
, как этот
private void initializeAndInjectComponent() {
mApplicationComponent =
DaggerApplicationComponent
.builder()
.threadingModule(new ThreadingModule(1))
.applicationModule(new ApplicationModule(this))
.networkModule(new NetworkModule(
MyService.API_SERVER_BASE_URL,
MyService.TIMEOUT))
.build();
mApplicationComponent.inject(this);
}
И я могу получить компонент для ввода в моем Activities
MyApplication application = MyApplication.get(this);
application.getApplicationComponent().inject(this);
Все работает отлично.
Чтобы добавить каждый метод, а также класс модуля, аннотируется с областью @Singleton
, все модули, относящиеся к ApplicationComponent
Теперь я хочу улучшить зависимости, и я видел множество примеров с пользовательскими областями, например @PerActivity
, @PerFragment
. У меня много вопросов, но об этом позже.
Итак, я создал ActivityComponent
@PerActivity
@Subcomponent(
modules = {
NetworkServiceModule.class,
ActivityModule.class,
PermissionModule.class
})
public interface ActivityComponent {
Activity activity();
void inject(BaseActivity baseActivity);
}
Все модули выглядят как
@PerActivity
@Module
public class ActivityModule {
private Activity mActivity;
public ActivityModule(Activity activity) {
this.mActivity = activity;
}
@Provides
@PerActivity
Activity provideActivity() {
return this.mActivity;
}
}
У меня есть следующие зависимости в моем BaseActivity
// Dependencies from ApplicationComponent
@Inject
protected ApplicationSettingsManager mApplicationSettingsManager;
@Inject
protected ScheduledThreadPoolExecutor mPoolExecutor;
// Dependencies from ActivityComponent
@Inject
protected SpiceManager mSpiceManager;
@Inject
protected PermissionController mPermissionController;
И в моем методе onCreate()
я впрыскиваю следующее
MyApplication application = MyApplication.get(this);
application.getApplicationComponent().activityComponent(new ActivityModule(this)).inject(this);
До создания подкомпонента ActivityComponent
это было
MyApplication application = MyApplication.get(this);
application.getApplicationComponent().inject(this);
Теперь я получил сообщение об ошибке
Error:(34, 10) error: com.octo.android.robospice.SpiceManager cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
BaseActivity.mSpiceManager
[injected field of type: com.octo.android.robospice.SpiceManager mSpiceManager]
Я не могу понять, где проблема, что я пропустил. Мои вопросы о облаках в кинжале2.
Все, кроме @Singleton
, игнорируется Кинжалом 2, верно?
Я не понимаю, как управляется жизнь компонента? У меня есть только одна идея.
-
Когда вы используете
@Singleton
, кинжал-аннотация создает объект в каком-то статическом пуле, который будет существовать в течение всего жизненного цикла приложения, и будет уничтожен, когда экземпляр JVM-процесса (dalvik VM, ART) будет уничтожен. -
Когда вы используете какую-либо другую аннотацию, для вас, как разработчика, лучше поддерживать код,
@PerActivity
,@PerFragment
- это просто нестандартная аннотация. И если вы разместите компонент@PerFragment
в классе Application, он будет жить до тех пор, пока приложение будет работать. Я прав? -
Итак, я понимаю это так: если кинжал найдет аннотацию
@Singleton
, она добавит статическую ссылку на компонент, когда она будет создана впервые, а в случае любой другой аннотации она не будет ссылаться на компонент.
Я был бы очень благодарен за любую помощь в описанных выше проблемах.
UPDATE
Спасибо David Medenjak
за отличный ответ, я получил гораздо лучшее понимание Dagger2
.
Я также нашел проблему, поскольку теперь я использую отдельный компонент Activity
, я забыл о двух строках в ApplicationComponent
и изменил inejction в моих MainActivity
на ActivityComponent
вместо ApplicationComponent
, поэтому наверняка не удалось разрешить зависимости от подкомпонента.
void inject(BaseActivity baseActivity);
void inject(MainAppActivity mainAppActivity);
Теперь все работает отлично, мне нравится Dagger2
и разделенная архитектура.