From a81a66bdb9841720cabd3114f91cbb19c018e21e Mon Sep 17 00:00:00 2001 From: Evgeny Dubravin Date: Fri, 29 Mar 2024 22:36:19 +0700 Subject: [PATCH] feature TI-194: [Android] DI --- app/src/main/AndroidManifest.xml | 6 ++--- .../ru/touchin/template/SingleActivity.kt | 5 ---- .../template/base/activity/BaseActivity.kt | 7 ++++- .../template/base/fragment/BaseFragment.kt | 5 +++- .../template/di/SharedComponentProvider.kt | 2 ++ .../template/di/modules/ViewModelModule.kt | 9 ++++++- .../template/di/viewmodel/ViewModelFactory.kt | 27 +++++++++++++++++++ app/src/main/res/layout/activity_main.xml | 24 ++++++++++++++--- app/src/main/res/layout/fragment_first.xml | 27 +++++++++++++++++++ app/src/main/res/layout/fragment_second.xml | 27 +++++++++++++++++++ 10 files changed, 124 insertions(+), 15 deletions(-) delete mode 100644 app/src/main/java/ru/touchin/template/SingleActivity.kt create mode 100644 app/src/main/res/layout/fragment_first.xml create mode 100644 app/src/main/res/layout/fragment_second.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 498225a..0f6717f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,12 +11,12 @@ android:label="@string/common_app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="false" - tools:ignore="GoogleAppIndexingWarning"> + tools:ignore="GoogleAppIndexingWarning" + android:theme="@style/AppTheme"> diff --git a/app/src/main/java/ru/touchin/template/SingleActivity.kt b/app/src/main/java/ru/touchin/template/SingleActivity.kt deleted file mode 100644 index e71c1db..0000000 --- a/app/src/main/java/ru/touchin/template/SingleActivity.kt +++ /dev/null @@ -1,5 +0,0 @@ -package ru.touchin.template - -import androidx.appcompat.app.AppCompatActivity - -class SingleActivity : AppCompatActivity() 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 index df11275..0100cf3 100644 --- a/app/src/main/java/ru/touchin/template/base/activity/BaseActivity.kt +++ b/app/src/main/java/ru/touchin/template/base/activity/BaseActivity.kt @@ -1,12 +1,17 @@ package ru.touchin.template.base.activity import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.ViewModel import ru.touchin.template.di.SharedComponent import ru.touchin.template.di.getSharedModule -class BaseActivity : AppCompatActivity() { +abstract class BaseActivity : AppCompatActivity() { + + protected val viewModel: T by lazy { createViewModelLazy().value } protected val viewModelFactory by lazy { getSharedComponent().viewModelFactory() } + abstract fun createViewModelLazy(): Lazy + 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 index c9c3c8e..7125d9e 100644 --- a/app/src/main/java/ru/touchin/template/base/fragment/BaseFragment.kt +++ b/app/src/main/java/ru/touchin/template/base/fragment/BaseFragment.kt @@ -1,12 +1,15 @@ package ru.touchin.template.base.fragment import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModel import ru.touchin.template.di.SharedComponent import ru.touchin.template.di.getSharedModule -class BaseFragment : Fragment() { +abstract class BaseFragment : Fragment() { protected val viewModelFactory by lazy { getSharedComponent().viewModelFactory() } + protected abstract fun createViewModelLazy(): Lazy + protected fun getSharedComponent(): SharedComponent = 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 index 0ee19ab..771a420 100644 --- a/app/src/main/java/ru/touchin/template/di/SharedComponentProvider.kt +++ b/app/src/main/java/ru/touchin/template/di/SharedComponentProvider.kt @@ -2,9 +2,11 @@ package ru.touchin.template.di import dagger.Module import ru.touchin.template.di.viewmodel.ViewModelFactory +import ru.touchin.template.feature.second.SecondViewModel interface SharedComponent { fun viewModelFactory(): ViewModelFactory + fun secondScreenViewModelFactory(): SecondViewModel.Factory } @Module 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 index 9331a01..781d5ad 100644 --- a/app/src/main/java/ru/touchin/template/di/modules/ViewModelModule.kt +++ b/app/src/main/java/ru/touchin/template/di/modules/ViewModelModule.kt @@ -5,9 +5,10 @@ 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 +import ru.touchin.template.feature.SingleViewModel +import ru.touchin.template.feature.first.FirstViewModel @Module interface ViewModelModule { @@ -19,4 +20,10 @@ interface ViewModelModule { @IntoMap @ViewModelKey(SingleViewModel::class) fun bindsSingleViewModel(viewModel: SingleViewModel): ViewModel + + @Binds + @IntoMap + @ViewModelKey(FirstViewModel::class) + fun bindsFirstViewModel(viewModel: FirstViewModel): 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 index 297984b..699e68c 100644 --- a/app/src/main/java/ru/touchin/template/di/viewmodel/ViewModelFactory.kt +++ b/app/src/main/java/ru/touchin/template/di/viewmodel/ViewModelFactory.kt @@ -1,7 +1,13 @@ package ru.touchin.template.di.viewmodel +import android.os.Bundle +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import androidx.lifecycle.AbstractSavedStateViewModelFactory +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import androidx.savedstate.SavedStateRegistryOwner import javax.inject.Inject import javax.inject.Provider @@ -14,4 +20,25 @@ class ViewModelFactory @Inject constructor( val viewModel = viewModels[modelClass]?.get() return viewModel as T } +} + +inline fun Fragment.assistedViewModel( + crossinline creator: (SavedStateHandle) -> VM, +): Lazy = viewModels { createAbstractSavedStateViewModelFactory(arguments, creator) } + +inline fun SavedStateRegistryOwner.createAbstractSavedStateViewModelFactory( + arguments: Bundle? = Bundle(), + crossinline creator: (SavedStateHandle) -> T, +): ViewModelProvider.Factory { + return object : AbstractSavedStateViewModelFactory( + owner = this@createAbstractSavedStateViewModelFactory, + defaultArgs = arguments, + ) { + @Suppress("UNCHECKED_CAST") + override fun create( + key: String, + modelClass: Class, + handle: SavedStateHandle, + ): T = creator(handle) as T + } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index a066a0d..9de21c1 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,6 +1,22 @@ - - + android:layout_height="match_parent" + android:background="@color/biometric_error_color"> + + + + + + diff --git a/app/src/main/res/layout/fragment_first.xml b/app/src/main/res/layout/fragment_first.xml new file mode 100644 index 0000000..a36f0ea --- /dev/null +++ b/app/src/main/res/layout/fragment_first.xml @@ -0,0 +1,27 @@ + + + + + +