В конце прошлого урока мы решили создавать свою реализацию даггер-компонента, чтобы нам было максимально понятно, что и как происходит.
Оглавление
4. Используем Context при создании объекта
6. Фрагмент в отдельный модуль
10. Заключение и полезные ссылки
Представим, что мы даггер. Нам дали интерфейс компонента AppComponent
AppComponent (:app)
@Component(modules = [DataModule::class]) interface AppComponent { fun injectTasksActivity(tasksActivity: TasksActivity) }
От нас требуется создать класс-реализацию.
Даггер создавал класс DaggerAppComponent, а мы создадим MyAppComponent
MyAppComponent (:app)
class MyAppComponent: AppComponent { override fun injectTasksActivity(tasksActivity: TasksActivity) { TODO("Not yet implemented") } }
Наш компонент должен уметь инджектить объекты в TasksActivity.
Самый простой вариант - это сделать так:
MyAppComponent (:app)
class MyAppComponent: AppComponent { override fun injectTasksActivity(tasksActivity: TasksActivity) { tasksActivity.database = Database() } }
И оно даже будет работать.
Но у нас создание Database явно описано в даггер-модуле DataModule. Поэтому надо использовать его:
MyAppComponent (:app)
class MyAppComponent: AppComponent { private val dataModule = DataModule() override fun injectTasksActivity(tasksActivity: TasksActivity) { tasksActivity.database = dataModule.provideDatabase() } }
Мы создаем экземпляр даггер-модуля, просим его создать нам Database и помещаем в TasksActivity. И это собственно вся работа компонента. Больше от него пока ничего не требуется.
Этот код является упрощенной версией того, что делает под капотом реальный компонент даггера. Билдер компонента мы тут не делаем, чтобы не усложнять. Нам главное видеть, как компонент создает и инджектит объекты.
Осталось в App классе вместо даггер компонента создавать и использовать наш компонент
App (:app)
class App: Application() { lateinit var appComponent: AppComponent override fun onCreate() { super.onCreate() // appComponent = DaggerAppComponent.create() appComponent = MyAppComponent() } }
Код TasksActivity не меняется, т.к. он работает с интерфейсом AppComponent, и ему не важно, какая там внутри реализация
class TasksActivity : AppCompatActivity() { @Inject lateinit var database: Database override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_tasks) (applicationContext as App).appComponent.injectTasksActivity(this) } }
Получаем от App нашу реализацию компонента и используем его для инджекта Database.
Схема объектов та же, что и раньше, только теперь там наш компонент вместо даггеровского
Результат
Чтобы нам лучше понимать, что происходит, мы создали и использовали свою реализацию компонента.
Внутри не оказалось ничего сложного. Компонент создает модули и использует их для создания объекта. И эти объекты потом просто вставляет в Activity. Т.е. компонент - это просто фабрика, которая создает для нас объекты.
В следующем уроке немного усложним пример, добавив Context в процесс создания объекта Database.
Присоединяйтесь к нам в Telegram:
- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance
- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
Комментарии
Гугл в своих мануалах почему то использует именно context
https://developer.android.com/training/dependency-injection/dagger-android
RSS лента комментариев этой записи