Я пытаюсь добавить dagger- android к проекту Kotlin и запутался, когда он требуется для создания модуля и когда достаточно просто объявить конструктор Inject.
Предположим, что есть следующий график зависимостей:
Activity
-> ViewModel
-> Repository
-> Webservice
-> Dao
-> Database
-> Application
Чтобы обеспечить ViewModel
для Activity
, мы создаем соответствующие модули для действия и фабрики ViewModel, а затем вручную создаем ViewModel в Activity следующим образом:
@Module
abstract class ActivityModule {
@ContributesAndroidInjector
abstract fun mainActivity(): MainActivity
}
// Skiping ViewModelKey and ViewModelFactory code for brevity
@Module
abstract class ViewModelModule {
@Binds
internal abstract fun bindViewModelFactory(
factory: ViewModelFactory
): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(MainViewModel::class)
internal abstract fun mainViewModel(viewModel: MainViewModel): ViewModel
}
class MainActivity : DaggerAppCompatActivity() {
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
...
viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(HomeViewModel::class.java)
}
}
Чтобы предоставить Repository
для ViewModel
, мы просто объявляем @Inject constructor
следующим образом:
class MainViewModel @Inject constructor(private val repository: Repository): ViewModel() {}
Чтобы предоставить Webservice
и Dao
для Repository
как а также Database
для Дао мы создаем соответствующие Модули следующим образом:
@Module
class NetworkModule {
@Provides
@Singleton
fun provideWebservice() = Webservice.create()
}
interface Webservice {
...
companion object Factory {
fun create(): Webservice {
...
return retrofit
}
}
}
@Module
class DataModule {
@Provides
@Singleton
fun provideApplicationDatabase(app: Application) =
AppDatabase.getDatabase(app)
@Provides
@Singleton
fun provideUserDao(db: AppDatabase) = db.userDao()
}
@Database(...)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object {
fun getDatabase(context: Context): AppDatabase {
...
return instance
}
}
}
И Application
предоставляется для Dabatabase
некоторыми волхвами c в AppComponent и в классе Application
@Singleton
@Component(modules = [
AndroidSupportInjectionModule::class,
NetworkModule::class,
DataModule::class,
ViewModelModule::class,
ActivityModule::class
])
interface AppComponent: AndroidInjector<App> {
@Component.Builder
interface Builder {
@BindsInstance
fun create(application: Application): Builder
fun build(): AppComponent
}
}
class App : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<out DaggerApplication> =
DaggerAppComponent.builder().create(this).build()
}
Вопросы :
- Как база данных получает экземпляр приложения? Это AndroidSupportInjectionModule, который делает magi c?
- Почему нам нужно создавать модули для веб-сервиса и базы данных, а не для репозитория? Можно ли аннотировать интерфейс Webservice и сам класс Database, чтобы пропустить создание для них отдельных модулей кинжала?