Как организовать модули и компоненты Dagger2 при использовании приложения для одного действия
У меня есть приложение, скажем, с 15 экранами. Существует 3 основных, совершенно отдельных вида деятельности:
LoginActivity
- довольно очевидный, некоторые вещи входаMainActivity
- большой, самый важныйTheOtherOneNotRelevantAtTheMoment
Я решил использовать Conductor
потому что я нашел жизненный цикл фрагмента слишком сложным, и для меня Conductor
сейчас "горячее дерьмо"
У меня есть много контроллеров Проводника. Большинство из них как XXXListController
с соответствующими XXXDetailController
, Все эти контроллеры живут только внутри MainActivity
, Это что-то вроде "единой активности-приложения". LoginActivity
был введен в основном из-за обратных вызовов от сторонних OAuths, таких как FbLogin и Google Login. Я просто пытаюсь сделать MainActivity
полностью мое - без каких-либо других странных действий.
Чтобы немного упорядочить зависимости, я решил использовать Dagger2. У меня довольно хороший опыт работы со Spring и JavaEE, поэтому я думаю, что это будет легко.
Я узнал несколько модулей без проблем:
AppModule
- с моими приложениями, такими как адрес сервера и т. д.AndroidModule
- с такими вещами, как SharedPreferences
, Application
Тогда я в значительной степени "импровизировал" с тем, как организовать свои взгляды. Вот что у меня есть:
- 3 дополнительные области применения:
ActivityScope
,ControllerScope
, а такжеServiceScope
- не имеет значения. - каждый
Controller
имеет свой собственный соответствующийModule
&Component
, Я читал, что это не может быть очень хорошей идеей, но я согласен с этим - каждыйController
является довольно независимым и имеет свой собственный уникальный набор зависимостей. ApplicationComponent
конечно корень иерархии.MainActivityComponent
это@Subcomponent
изApplicationComponent
XXXControllerComponent
это@Subcomponent
изMainActivityComponent
Внедрить зависимости внутри MainActivity
Я использую, и я нашел этот код довольно распространенным:
protected void injectDependencies(ApplicationComponent component) {
component.plus(new MainActivityModule(this)).inject(this);
}
Проблема возникает, когда я хочу создать и внедрить зависимости в мой Controller
s.
MainActivity
выглядит следующим образом:
@ActivityScope
@Subcomponent(modules = {
MainActivityModule.class
})
public interface MainActivityComponent {
XXXListComponent newXXXListComponent(XXXListModule xxxListModule);
void inject(MainActivity activity);
}
На данный момент типичный Controller
выглядит так:
@ControllerScope
@Subcomponent(modules = {
XXXListModule.class
})
public interface XXXListComponent {
void inject(XXXListController controller);
}
и соответствующий Module
:
@Module
public class XXXListModule {
private XXXListController listController;
public XXXListModule(XXXListController listController) {
this.listController = listController;
}
@Provides
@ControllerScope
public XXXListController getMainView() {
return ListController;
}
// other not important
}
В основном каждый Controller
должен быть синглтон - я не хочу иметь два экземпляра внутри MainActivity
- но это не обязательно.
Проблема в том, как создать Controller
правильный путь. В данный момент, MainActivity
сделайте это следующим образом:
router.pushController(RouterTransaction.with(new XXXListController()));
Я не уверен в этом, зачем создавать Controller
рукой?
внутри Controller
в onCreateView()
Я ввел все необходимые зависимости - на мой взгляд, очень некрасиво:
((MainActivity) getActivity()).getMainActivityComponent()
.newXXXListComponent(new XXXListModule(this))
.inject(this);
Этот длинный вопрос помогает мне систематизировать мои знания о Кинжале - возможно, кто-то найдет это полезным. Но! Для тех Stackruers, которые достигают этой линии, это хороший способ или есть какой-то другой, лучший способ сделать это?
1 ответ
Я не уверен, что полностью понимаю ваш вопрос, но, поскольку у вас есть несколько Активов, вы, вероятно, хотите сделать инъекцию внутри своего Приложения, а не MainActivity. В противном случае они больше не будут синглетонами, так как действия будут воссозданы при переходе между ними. Например, если вы делаете класс с именем ConductorApplication
:
public class ConductorApplication extends Application {
static AppComponent app_component;
static ClockComponent component;
@Override
public void onCreate() {
super.onCreate();
app_component = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
component = createComponent();
}
protected ClockComponent createComponent() {
return DaggerClockComponent.builder().build();
}
public static ClockComponent getClockComponent() {
return component;
}
public ClockComponent component() {
return component;
}
public static AppComponent GetAppComponent() {
return app_component;
}
}
Затем внутри, когда ваш контроллер создан, например, внутри вашего inflateView()
в HomeController
public class HomeController extends BaseController {
private HomeViewModel homeViewModel;
private ControllerHomeBinding binding;
@Inject
Clock clock;
@NonNull
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
ConductorApplication.getClockComponent().inject(this);
return inflater.inflate(R.layout.controller_home, container, false);
...
}
Если вы еще этого не сделали, вам может потребоваться добавить:
<application
android:name=".ConductorApplication"
...
<activity
android:name=".MainActivity"
...
</activity>
</application>
внутри вашего AndroidMainifest.xml