Создание Android Instant App с компонентом приложения из кинжала

В настоящее время я экспериментирую с InstantApps и хочу включить кинжал в свой проект.

У меня возникла проблема с настройкой приложения AppComponent. Мой компонент приложения включает все функциональные кинжальные модули моего приложения.

У меня в основном есть:

  • Один базовый модуль приложения, содержащий класс приложения
  • Несколько функций с каждым модулем кинжала за активность, все с базой как зависимость.
  • Один модуль приложения и мгновенный модуль, одновременно импортирующий все функции и базовый модуль приложения.

Я пытаюсь выяснить настройку перед добавлением модуля Instant App.

Из документации и проектов проекта InstantApps. Кажется, что класс Application должен находиться в базе. Из документации Dagger, чтобы установить кинжал:

 DaggerYourAppComponent.create().inject(this);

Должен быть включен в ваш класс приложения. Однако это кажется невозможным, поскольку AppComponent должен ссылаться на все модули кинжалов.

Мои вопросы:

  • Где я должен добавить свой модуль кинжала AppComponent?
  • Должен ли я сохранять свое приложение в модуле приложения, а не на базе?
  • Любой репортаж GitHub или документация вокруг кинжала с Instant Apps?

Спасибо

Ответы

Ответ 1

  • Dagger2 очень поддерживается мгновенными приложениями. Вы можете создавать классы компонентов для каждого функционального модуля и соответствующего класса провайдера Dagger для отображения экземпляра класса компонента для каждого функционального модуля.
  • Каждый класс компонентов модуля может объявлять инжекционные методы для классов, содержащихся только в этом функциональном модуле.
  • Кроме того, вы также можете иметь класс компонента приложения в базовый модуль для инъекций широкого применения.
  • Класс компонента приложения может быть создан в Класс приложения, включенный в базовый модуль и подверженный другим функциональных модулей через статический метод в классе приложения.

Вот пример кода инъекции Dagger2 с мгновенными приложениями, чтобы сделать вещи более ясными. https://github.com/willowtreeapps/android-instant-apps-demo

Ответ 2

Я написал статью об этом со многими подробностями: Dagger2 для модульной архитектуры, но после короткого ответа.

Вы должны использовать Dagger2 по-другому. Вместо использования модуля или подкомпонента для каждого функционального модуля вам необходимо использовать компонент с зависимостью от базового AppComponent.

В одном модуле мы обычно делаем что-то вроде этого:

@Singleton
@Component(modules = arrayOf(NetworkModule::class, RepositoryModule::class, 
                     SubcomponentModule::class))
interface ApplicationComponent : AndroidInjector<MyApplication> {
  val userRepository: UserRepository
  val apiService: ApiService
}

@Module
object NetworkModule {
  @Provides
  @Singleton
  @JvmStatic
  fun provideApiService(okHttp: OkHttp): ApiService {
    return ApiSerive(okHttp)
  }
 }

Но, как вы сказали, у вас нет доступа к SubComponentModule, который может быть в другом модуле или контрольных модулях кинжалов в другом функциональном модуле.

Вы можете просто создать новый модуль кинжала в функциональном модуле в зависимости от ApplicationComponent следующим образом:

@Browser
@Component(modules = [(BrowserModule::class)],
      dependencies = [(AppComponent::class)])
interface BrowserComponent : AndroidInjector<AppCompatActivity> {
  @Component.Builder
  abstract class Builder: AndroidInjector.Builder<AppCompatActivity>(){
    /**
    *  explicity declare to Dagger2
    * that this builder will accept an AppComponent instance
    **/
    abstract fun plus(component: AppComponent): Builder
  }
}

И соответствующая функция функции будет строить компонент:

class BrowserActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    DaggerBrowserComponent
        .builder()
        /**
         * we have to provide an instance of the AppComponent or
         * any other dependency for this component
         **/
        .plus((application as MyApplication).component)
        .build()
        .inject(this)
  }
}