feature TI-193: [Android] Реализовать ViewModel Factory

This commit is contained in:
Evgeny Dubravin 2024-03-28 17:10:25 +07:00
parent 70819e7f41
commit 417547d44e
16 changed files with 196 additions and 4 deletions

View File

@ -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)

View File

@ -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()
}

View File

@ -0,0 +1,6 @@
package ru.touchin.template
import androidx.lifecycle.ViewModel
import javax.inject.Inject
class SingleViewModel @Inject constructor() : ViewModel()

View File

@ -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()
}

View File

@ -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()
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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()
}

View File

@ -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
}

View File

@ -0,0 +1,11 @@
package ru.touchin.template.di.modules
import dagger.Module
@Module(
includes = [
RepositoryModule::class,
NetworkModule::class
]
)
class AppModule

View File

@ -0,0 +1,7 @@
package ru.touchin.template.di.modules
import dagger.Module
@Module
class NetworkModule {
}

View File

@ -0,0 +1,7 @@
package ru.touchin.template.di.modules
import dagger.Module
@Module
class RepositoryModule {
}

View File

@ -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
}

View File

@ -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<Class<out ViewModel>, Provider<ViewModel>>
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
val viewModel = viewModels[modelClass]?.get()
return viewModel as T
}
}

View File

@ -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<out ViewModel>)

1
common-template Submodule

@ -0,0 +1 @@
Subproject commit d6f303bf879a2da1706cfdacaf2bbe0c326044bd