Как организовать модули и компоненты 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);
}

Проблема возникает, когда я хочу создать и внедрить зависимости в мой Controllers.

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

Другие вопросы по тегам