Лучшая инъекция зависимости Dagger на основе типа сборки и вкуса?

Я использую aproach для предоставления модулей Dagger, описанных в ответе на этот вопрос Рабочий процесс настройки Android для продукта Ароматизаторы

Наш подход немного отличается - у нас есть Modules в debug тип сборки в src/debug/java и release тип сборки в src/release/java. Наш основной модуль называется ApplicationModule, он включает в себя все остальные.

Modules в src/debug/java обеспечивает некоторое настраиваемое поведение для отладки, ведения журнала и т. Д. И переопределяет ApplcationModule.

Теперь у нас есть потребность в настраиваемом поведении, основанном на вкусе приложения.

Какой будет правильный подход к этому?

Например, варианты от A до C должны обеспечивать настраиваемое поведение, а варианты от D до F должны обеспечивать базовое поведение по умолчанию.

Пока что придумал такой.

  • Все разновидности (не типы сборки) имеют один и тот же класс в src/flavorX/java/com.application.FlavorModule
  • Чтобы избежать дублирования кода, только варианты от A до C обеспечивают настраиваемое поведение, в то время как другие полностью пусты, чтобы проект мог компилироваться. И поведение по умолчанию предоставляется моему модулю в src/main/java

Есть ли лучший способ добиться такого результата? Потому что я не люблю пустые src/flavorX/java/com.application.FlavorModule и не люблю дублирование кода ...


person Martynas Jurkus    schedule 11.02.2014    source источник
comment
проверьте этот проект github.com/athkalia/Just-Another-Android-App   -  person Basheer AL-MOMANI    schedule 27.02.2019


Ответы (2)


Немного сложно, но вот как я это сделал:

Создайте интерфейс MainComponent и сохраните его в src / main, он должен содержать все, что не зависит от вкуса.

public interface MainComponent {
    void inject(MyApplication o);

    void inject(BusinessObject o);

    Foo getFoo();

    Activitycomponent plusActivityComponent(ActivityModule activityModule);

}

Внутри каждого аромата создайте интерфейс, унаследованный от приведенного выше.

public interface FlavorComponent extends MainComponent {
//flavor specific injection stuff similar to SourceComponent
}

В Debug / Beta / Release создайте фактический компонент и расширьте FlavorComponent (предоставив вам все тонкости, специфичные для вкуса).

@Singleton
 @Component(modules = {ApplicationModule.class, FlavorModule.class,
         BetaApplicationModule.class, AnotherModuleJustBecause.class})
public interface ApplicationComponent extends FlavorComponent {
     void inject(NYTApplication a);

 }

Обратите внимание, что вы также можете включить модуль FlavorModule для конкретного аромата, который может отличаться для каждого аромата или не включать его в Release при включении в бета-версию.

Также включите ComponentFactory в Debug / Beta / Release, возвращающий общий интерфейс компонентов Flavor.

public class ComponentFactory {

public static final FlavorComponent getComponent(Application context) {
        return DaggerApplicationComponent.builder()
                .applicationModule(new ApplicationModule(context))
                .build();
    }

и, наконец, из вашего вызова класса Application:

ComponentFactory.getComponent(this).inject(this);

Фабрика компонентов вернет компонент типа сборки, который расширит компонент Flavor.

person FriendlyMikhail    schedule 13.10.2015
comment
Глядя на ваш ComponentFactory, я не понимаю, почему ваша последняя строка кода не ComponentFactory.getComponent(this).inject(this). Могли бы вы объяснить? - person Kevin Krumwiede; 08.12.2015
comment
Это может прояснить ситуацию, прочитав статью: medium.com/@theMikhail/flavoring -ваш-кинжал-14ab8bcef9f8 - person Juan Mendez; 05.01.2018

Мое решение было адаптацией этой статьи, цитированной выше.

У меня есть интерфейсный вызов ApplicationComponent в src / main:

    @Singleton
    @Component(modules = [

        FlavorModule::class,

        Anyothermoduleyouhave::class

    ])

    interface ApplicationComponent {}

Теперь внутри каждой папки ароматов вам нужно создать 2 файла:

  1. FlavorModule (абстрактный класс для вызова вашей конфигурации)
  2. FlavorConfig (конфигурация или любой нужный вам код вкуса)

кстати: если у вас нет исходной папки, вы можете создать, добавив в свой файл gradle:

        java.srcDirs += ['src/main/kotlin', 'src/myFlavorCode/kotlin']

а также создание папки kotlin

FlavorModule:

    @Module
    class FlavorModule {

        @[Provides Singleton]
        fun getConfig(config: MySpecificFlavor1Config): FlavorConfig

    }

FlavorConfig

    class MySpecificFlavor1Config @Inject constructor() : FlavorConfig {
        override fun getMyValueThatImLookingFor() = "flavor 1 woooooow"
    }

Сделайте то же самое для аромата 2.

Важно: чтобы эта работа работала динамически с помощью dagger, используйте один и тот же путь к пакету для обоих классов FlavorModule / FlavorConfig, например для пакета br.com.main.config, таким образом dagger понимает, какой FlavorModule использовать

person Igor Romcy    schedule 07.10.2020
comment
Я действительно не понимаю, почему нам нужно использовать abstract class, abstract fun и @[Binds Singleton] для модуля аромата. Если мы можем просто использовать class, fun и @Provides соответственно - person Dannie; 10.03.2021