From 417547d44e25e1e33ffcf0f0bb06ad3c9f0c0caa Mon Sep 17 00:00:00 2001 From: Evgeny Dubravin Date: Thu, 28 Mar 2024 17:10:25 +0700 Subject: [PATCH] =?UTF-8?q?feature=20TI-193:=20[Android]=20=D0=A0=D0=B5?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20ViewMo?= =?UTF-8?q?del=20Factory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 3 -- app/src/main/java/ru/touchin/template/App.kt | 15 +++++++++- .../ru/touchin/template/SingleViewModel.kt | 6 ++++ .../template/base/activity/BaseActivity.kt | 12 ++++++++ .../template/base/fragment/BaseFragment.kt | 12 ++++++++ .../ru/touchin/template/di/AppComponent.kt | 30 +++++++++++++++++++ .../main/java/ru/touchin/template/di/DI.kt | 16 ++++++++++ .../touchin/template/di/SharedComponentExt.kt | 17 +++++++++++ .../template/di/SharedComponentProvider.kt | 15 ++++++++++ .../touchin/template/di/modules/AppModule.kt | 11 +++++++ .../template/di/modules/NetworkModule.kt | 7 +++++ .../template/di/modules/RepositoryModule.kt | 7 +++++ .../template/di/modules/ViewModelModule.kt | 22 ++++++++++++++ .../template/di/viewmodel/ViewModelFactory.kt | 17 +++++++++++ .../template/di/viewmodel/ViewModelKey.kt | 9 ++++++ common-template | 1 + 16 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/ru/touchin/template/SingleViewModel.kt create mode 100644 app/src/main/java/ru/touchin/template/base/activity/BaseActivity.kt create mode 100644 app/src/main/java/ru/touchin/template/base/fragment/BaseFragment.kt create mode 100644 app/src/main/java/ru/touchin/template/di/AppComponent.kt create mode 100644 app/src/main/java/ru/touchin/template/di/DI.kt create mode 100644 app/src/main/java/ru/touchin/template/di/SharedComponentExt.kt create mode 100644 app/src/main/java/ru/touchin/template/di/SharedComponentProvider.kt create mode 100644 app/src/main/java/ru/touchin/template/di/modules/AppModule.kt create mode 100644 app/src/main/java/ru/touchin/template/di/modules/NetworkModule.kt create mode 100644 app/src/main/java/ru/touchin/template/di/modules/RepositoryModule.kt create mode 100644 app/src/main/java/ru/touchin/template/di/modules/ViewModelModule.kt create mode 100644 app/src/main/java/ru/touchin/template/di/viewmodel/ViewModelFactory.kt create mode 100644 app/src/main/java/ru/touchin/template/di/viewmodel/ViewModelKey.kt create mode 160000 common-template diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5103e8c..a7d316a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,8 +1,5 @@ plugins { id(Plugins.ANDROID_APP_PLUGIN_WITH_DEFAULT_CONFIG) - id(libs.plugins.android.application.get().pluginId) - id(libs.plugins.kotlin.android.get().pluginId) - id(libs.plugins.kotlin.kapt.get().pluginId) alias(libs.plugins.google.services) alias(libs.plugins.firebase.crashlytics) alias(libs.plugins.firebase.perf) diff --git a/app/src/main/java/ru/touchin/template/App.kt b/app/src/main/java/ru/touchin/template/App.kt index c6ffdc1..0048de1 100644 --- a/app/src/main/java/ru/touchin/template/App.kt +++ b/app/src/main/java/ru/touchin/template/App.kt @@ -1,5 +1,18 @@ package ru.touchin.template import android.app.Application +import ru.touchin.template.di.DI +import ru.touchin.template.di.SharedComponent +import ru.touchin.template.di.SharedComponentProvider -class App : Application() +class App : Application(), SharedComponentProvider { + + override fun onCreate() { + super.onCreate() + + DI.init(applicationContext) + DI.getComponent().inject(this) + } + + override fun getModule(): SharedComponent = DI.getComponent() +} diff --git a/app/src/main/java/ru/touchin/template/SingleViewModel.kt b/app/src/main/java/ru/touchin/template/SingleViewModel.kt new file mode 100644 index 0000000..15b24f0 --- /dev/null +++ b/app/src/main/java/ru/touchin/template/SingleViewModel.kt @@ -0,0 +1,6 @@ +package ru.touchin.template + +import androidx.lifecycle.ViewModel +import javax.inject.Inject + +class SingleViewModel @Inject constructor() : ViewModel() \ No newline at end of file diff --git a/app/src/main/java/ru/touchin/template/base/activity/BaseActivity.kt b/app/src/main/java/ru/touchin/template/base/activity/BaseActivity.kt new file mode 100644 index 0000000..df11275 --- /dev/null +++ b/app/src/main/java/ru/touchin/template/base/activity/BaseActivity.kt @@ -0,0 +1,12 @@ +package ru.touchin.template.base.activity + +import androidx.appcompat.app.AppCompatActivity +import ru.touchin.template.di.SharedComponent +import ru.touchin.template.di.getSharedModule + +class BaseActivity : AppCompatActivity() { + + protected val viewModelFactory by lazy { getSharedComponent().viewModelFactory() } + + protected fun getSharedComponent(): SharedComponent = getSharedModule() +} \ No newline at end of file diff --git a/app/src/main/java/ru/touchin/template/base/fragment/BaseFragment.kt b/app/src/main/java/ru/touchin/template/base/fragment/BaseFragment.kt new file mode 100644 index 0000000..c9c3c8e --- /dev/null +++ b/app/src/main/java/ru/touchin/template/base/fragment/BaseFragment.kt @@ -0,0 +1,12 @@ +package ru.touchin.template.base.fragment + +import androidx.fragment.app.Fragment +import ru.touchin.template.di.SharedComponent +import ru.touchin.template.di.getSharedModule + +class BaseFragment : Fragment() { + + protected val viewModelFactory by lazy { getSharedComponent().viewModelFactory() } + + protected fun getSharedComponent(): SharedComponent = getSharedModule() +} \ No newline at end of file diff --git a/app/src/main/java/ru/touchin/template/di/AppComponent.kt b/app/src/main/java/ru/touchin/template/di/AppComponent.kt new file mode 100644 index 0000000..f4b7320 --- /dev/null +++ b/app/src/main/java/ru/touchin/template/di/AppComponent.kt @@ -0,0 +1,30 @@ +package ru.touchin.template.di + +import android.content.Context +import dagger.BindsInstance +import dagger.Component +import javax.inject.Singleton +import ru.touchin.template.App +import ru.touchin.template.di.modules.AppModule +import ru.touchin.template.di.modules.ViewModelModule + +@Component( + modules = [ + AppModule::class, + ViewModelModule::class + ] +) +@Singleton +interface AppComponent : SharedComponent { + + @Component.Builder + interface Builder { + + @BindsInstance + fun appContext(appContext: Context): Builder + + fun build(): AppComponent + } + + fun inject(entry: App) +} \ No newline at end of file diff --git a/app/src/main/java/ru/touchin/template/di/DI.kt b/app/src/main/java/ru/touchin/template/di/DI.kt new file mode 100644 index 0000000..626c007 --- /dev/null +++ b/app/src/main/java/ru/touchin/template/di/DI.kt @@ -0,0 +1,16 @@ +package ru.touchin.template.di + +import android.content.Context + +object DI { + + private lateinit var appComponent: AppComponent + + fun init(context: Context) { + appComponent = DaggerAppComponent.builder() + .appContext(context) + .build() + } + + fun getComponent(): AppComponent = appComponent +} \ No newline at end of file diff --git a/app/src/main/java/ru/touchin/template/di/SharedComponentExt.kt b/app/src/main/java/ru/touchin/template/di/SharedComponentExt.kt new file mode 100644 index 0000000..36993ee --- /dev/null +++ b/app/src/main/java/ru/touchin/template/di/SharedComponentExt.kt @@ -0,0 +1,17 @@ +package ru.touchin.template.di + +import android.app.Activity +import android.content.Context +import androidx.fragment.app.Fragment + +fun Context.getSharedModule(): SharedComponent { + return (applicationContext as SharedComponentProvider).getModule() +} + +fun Activity.getSharedModule(): SharedComponent { + return (applicationContext as SharedComponentProvider).getModule() +} + +fun Fragment.getSharedModule(): SharedComponent { + return requireContext().getSharedModule() +} \ No newline at end of file diff --git a/app/src/main/java/ru/touchin/template/di/SharedComponentProvider.kt b/app/src/main/java/ru/touchin/template/di/SharedComponentProvider.kt new file mode 100644 index 0000000..0ee19ab --- /dev/null +++ b/app/src/main/java/ru/touchin/template/di/SharedComponentProvider.kt @@ -0,0 +1,15 @@ +package ru.touchin.template.di + +import dagger.Module +import ru.touchin.template.di.viewmodel.ViewModelFactory + +interface SharedComponent { + fun viewModelFactory(): ViewModelFactory +} + +@Module +class SharedModule + +interface SharedComponentProvider { + fun getModule(): SharedComponent +} \ No newline at end of file diff --git a/app/src/main/java/ru/touchin/template/di/modules/AppModule.kt b/app/src/main/java/ru/touchin/template/di/modules/AppModule.kt new file mode 100644 index 0000000..0943510 --- /dev/null +++ b/app/src/main/java/ru/touchin/template/di/modules/AppModule.kt @@ -0,0 +1,11 @@ +package ru.touchin.template.di.modules + +import dagger.Module + +@Module( + includes = [ + RepositoryModule::class, + NetworkModule::class + ] +) +class AppModule \ No newline at end of file diff --git a/app/src/main/java/ru/touchin/template/di/modules/NetworkModule.kt b/app/src/main/java/ru/touchin/template/di/modules/NetworkModule.kt new file mode 100644 index 0000000..8c14718 --- /dev/null +++ b/app/src/main/java/ru/touchin/template/di/modules/NetworkModule.kt @@ -0,0 +1,7 @@ +package ru.touchin.template.di.modules + +import dagger.Module + +@Module +class NetworkModule { +} \ No newline at end of file diff --git a/app/src/main/java/ru/touchin/template/di/modules/RepositoryModule.kt b/app/src/main/java/ru/touchin/template/di/modules/RepositoryModule.kt new file mode 100644 index 0000000..f995563 --- /dev/null +++ b/app/src/main/java/ru/touchin/template/di/modules/RepositoryModule.kt @@ -0,0 +1,7 @@ +package ru.touchin.template.di.modules + +import dagger.Module + +@Module +class RepositoryModule { +} \ No newline at end of file diff --git a/app/src/main/java/ru/touchin/template/di/modules/ViewModelModule.kt b/app/src/main/java/ru/touchin/template/di/modules/ViewModelModule.kt new file mode 100644 index 0000000..9331a01 --- /dev/null +++ b/app/src/main/java/ru/touchin/template/di/modules/ViewModelModule.kt @@ -0,0 +1,22 @@ +package ru.touchin.template.di.modules + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import ru.touchin.template.SingleViewModel +import ru.touchin.template.di.viewmodel.ViewModelFactory +import ru.touchin.template.di.viewmodel.ViewModelKey + +@Module +interface ViewModelModule { + + @Binds + fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory + + @Binds + @IntoMap + @ViewModelKey(SingleViewModel::class) + fun bindsSingleViewModel(viewModel: SingleViewModel): ViewModel +} \ No newline at end of file diff --git a/app/src/main/java/ru/touchin/template/di/viewmodel/ViewModelFactory.kt b/app/src/main/java/ru/touchin/template/di/viewmodel/ViewModelFactory.kt new file mode 100644 index 0000000..297984b --- /dev/null +++ b/app/src/main/java/ru/touchin/template/di/viewmodel/ViewModelFactory.kt @@ -0,0 +1,17 @@ +package ru.touchin.template.di.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import javax.inject.Inject +import javax.inject.Provider + +class ViewModelFactory @Inject constructor( + private val viewModels: MutableMap, Provider> +) : ViewModelProvider.Factory { + + @Suppress("UNCHECKED_CAST") + override fun create(modelClass: Class): T { + val viewModel = viewModels[modelClass]?.get() + return viewModel as T + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/touchin/template/di/viewmodel/ViewModelKey.kt b/app/src/main/java/ru/touchin/template/di/viewmodel/ViewModelKey.kt new file mode 100644 index 0000000..1f76f60 --- /dev/null +++ b/app/src/main/java/ru/touchin/template/di/viewmodel/ViewModelKey.kt @@ -0,0 +1,9 @@ +package ru.touchin.template.di.viewmodel + +import androidx.lifecycle.ViewModel +import dagger.MapKey +import kotlin.reflect.KClass + +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) +@MapKey +annotation class ViewModelKey(val value: KClass) \ No newline at end of file diff --git a/common-template b/common-template new file mode 160000 index 0000000..d6f303b --- /dev/null +++ b/common-template @@ -0,0 +1 @@ +Subproject commit d6f303bf879a2da1706cfdacaf2bbe0c326044bd