diff --git a/app/build.gradle b/app/build.gradle index d8129192..270b4c50 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,8 +2,9 @@ plugins { id 'com.android.application' id 'kotlin-android' id 'kotlin-kapt' - id 'org.jetbrains.kotlin.plugin.serialization' version '1.4.21' + id 'org.jetbrains.kotlin.plugin.serialization' version '1.4.30' id 'dk.nstack.translation.plugin' + id 'dagger.hilt.android.plugin' } translation { @@ -97,10 +98,10 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - implementation "com.google.dagger:dagger-android:${versions.dagger}" - implementation "com.google.dagger:dagger-android-support:${versions.dagger}" - kapt "com.google.dagger:dagger-compiler:${versions.dagger}" - kapt "com.google.dagger:dagger-android-processor:${versions.dagger}" + + implementation "com.google.dagger:hilt-android:${versions.hilt}" + kapt "com.google.dagger:hilt-compiler:${versions.hilt}" + implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0") implementation("com.squareup.retrofit2:retrofit:2.9.0") diff --git a/app/src/main/java/com/monstarlab/App.kt b/app/src/main/java/com/monstarlab/App.kt index cb00e188..a8fe7dbc 100644 --- a/app/src/main/java/com/monstarlab/App.kt +++ b/app/src/main/java/com/monstarlab/App.kt @@ -1,13 +1,13 @@ package com.monstarlab +import android.app.Application import com.monstarlab.features.nstack.Translation -import com.monstarlab.injection.components.DaggerAppComponent -import dagger.android.AndroidInjector -import dagger.android.DaggerApplication +import dagger.hilt.android.HiltAndroidApp import dk.nodes.nstack.kotlin.NStack import timber.log.Timber -class App : DaggerApplication() { +@HiltAndroidApp +class App : Application() { override fun onCreate() { super.onCreate() @@ -17,8 +17,4 @@ class App : DaggerApplication() { Timber.plant(Timber.DebugTree()) } } - - override fun applicationInjector(): AndroidInjector { - return DaggerAppComponent.factory().create(this) - } } diff --git a/app/src/main/java/com/monstarlab/arch/base/BaseActivity.kt b/app/src/main/java/com/monstarlab/arch/base/BaseActivity.kt deleted file mode 100644 index 5d4edb87..00000000 --- a/app/src/main/java/com/monstarlab/arch/base/BaseActivity.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.monstarlab.arch.base - -import android.content.Context -import android.os.Bundle -import androidx.annotation.LayoutRes -import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import com.monstarlab.arch.extensions.getViewModel -import com.monstarlab.arch.extensions.lifecycleAwareLazy -import dagger.android.AndroidInjection -import dagger.android.DispatchingAndroidInjector -import dagger.android.HasAndroidInjector -import dk.nodes.nstack.kotlin.inflater.NStackBaseContext -import javax.inject.Inject - -abstract class BaseActivity : AppCompatActivity, HasAndroidInjector { - - constructor() : super() - constructor(@LayoutRes resId: Int) : super(resId) - - @Inject - lateinit var viewModelFactory: ViewModelProvider.Factory - - @Inject - lateinit var androidInjector: DispatchingAndroidInjector - - override fun onCreate(savedInstanceState: Bundle?) { - AndroidInjection.inject(this) - super.onCreate(savedInstanceState) - } - - override fun attachBaseContext(newBase: Context) { - super.attachBaseContext(NStackBaseContext(newBase)) - } - - protected inline fun getViewModel(): VM = - getViewModel(viewModelFactory) - - protected inline fun viewModel(): Lazy { - return lifecycleAwareLazy(this) { getViewModel() } - } - - override fun androidInjector() = androidInjector -} diff --git a/app/src/main/java/com/monstarlab/arch/base/BaseFragment.kt b/app/src/main/java/com/monstarlab/arch/base/BaseFragment.kt deleted file mode 100644 index ea9f0211..00000000 --- a/app/src/main/java/com/monstarlab/arch/base/BaseFragment.kt +++ /dev/null @@ -1,57 +0,0 @@ -package com.monstarlab.arch.base - -import android.content.Context -import android.os.Bundle -import androidx.annotation.LayoutRes -import androidx.fragment.app.Fragment -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import com.google.android.material.transition.MaterialFadeThrough -import com.monstarlab.arch.extensions.getSharedViewModel -import com.monstarlab.arch.extensions.getViewModel -import com.monstarlab.arch.extensions.lifecycleAwareLazy -import dagger.android.DispatchingAndroidInjector -import dagger.android.HasAndroidInjector -import dagger.android.support.AndroidSupportInjection -import javax.inject.Inject - -abstract class BaseFragment : Fragment, HasAndroidInjector { - - constructor() - constructor(@LayoutRes resId: Int) : super(resId) - - @Inject - lateinit var viewModelFactory: ViewModelProvider.Factory - - @Inject - lateinit var androidInjector: DispatchingAndroidInjector - - protected inline fun getViewModel(): VM = - getViewModel(viewModelFactory) - - protected inline fun getSharedViewModel(): VM = - getSharedViewModel(viewModelFactory) - - protected inline fun viewModel(): Lazy = lifecycleAwareLazy(this) { - getViewModel() - } - - protected inline fun sharedViewModel(): Lazy = - lifecycleAwareLazy(this) { - getSharedViewModel() - } - - override fun onAttach(context: Context) { - AndroidSupportInjection.inject(this) - super.onAttach(context) - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - enterTransition = MaterialFadeThrough() - exitTransition = MaterialFadeThrough() - } - - override fun androidInjector() = androidInjector -} diff --git a/app/src/main/java/com/monstarlab/features/login/LoginFragment.kt b/app/src/main/java/com/monstarlab/features/login/LoginFragment.kt index 6d764e85..43429260 100644 --- a/app/src/main/java/com/monstarlab/features/login/LoginFragment.kt +++ b/app/src/main/java/com/monstarlab/features/login/LoginFragment.kt @@ -3,22 +3,25 @@ package com.monstarlab.features.login import android.os.Bundle import android.view.View import androidx.core.view.isVisible +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels import androidx.lifecycle.loadingFlow import androidx.lifecycle.viewErrorFlow import androidx.navigation.fragment.findNavController import androidx.transition.TransitionManager import com.monstarlab.R -import com.monstarlab.arch.base.BaseFragment import com.monstarlab.arch.extensions.collectFlow import com.monstarlab.arch.extensions.onClick import com.monstarlab.arch.extensions.snackErrorFlow import com.monstarlab.arch.extensions.viewBinding import com.monstarlab.arch.extensions.visibilityFlow import com.monstarlab.databinding.FragmentLoginBinding +import dagger.hilt.android.AndroidEntryPoint -class LoginFragment : BaseFragment(R.layout.fragment_login) { +@AndroidEntryPoint +class LoginFragment : Fragment(R.layout.fragment_login) { - private val viewModel by viewModel() + private val viewModel by viewModels() private val binding by viewBinding(FragmentLoginBinding::bind) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/monstarlab/features/login/LoginViewModel.kt b/app/src/main/java/com/monstarlab/features/login/LoginViewModel.kt index 2d97dfa3..da017479 100644 --- a/app/src/main/java/com/monstarlab/features/login/LoginViewModel.kt +++ b/app/src/main/java/com/monstarlab/features/login/LoginViewModel.kt @@ -8,10 +8,12 @@ import com.monstarlab.arch.extensions.LoadingAware import com.monstarlab.arch.extensions.ViewErrorAware import com.monstarlab.arch.extensions.onSuccess import com.monstarlab.core.usecases.user.LoginUseCase +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.launchIn import javax.inject.Inject +@HiltViewModel class LoginViewModel @Inject constructor( private val loginUseCase: LoginUseCase ) : ViewModel(), ViewErrorAware, LoadingAware { diff --git a/app/src/main/java/com/monstarlab/features/main/MainActivity.kt b/app/src/main/java/com/monstarlab/features/main/MainActivity.kt index 0857082b..26f5d33a 100644 --- a/app/src/main/java/com/monstarlab/features/main/MainActivity.kt +++ b/app/src/main/java/com/monstarlab/features/main/MainActivity.kt @@ -1,10 +1,12 @@ package com.monstarlab.features.main import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity import com.monstarlab.R -import com.monstarlab.arch.base.BaseActivity +import dagger.hilt.android.AndroidEntryPoint -class MainActivity : BaseActivity(R.layout.activity_main) { +@AndroidEntryPoint +class MainActivity : AppCompatActivity(R.layout.activity_main) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setupNStack() diff --git a/app/src/main/java/com/monstarlab/features/resources/ResourceFragment.kt b/app/src/main/java/com/monstarlab/features/resources/ResourceFragment.kt index 96379d9c..3fe152f3 100644 --- a/app/src/main/java/com/monstarlab/features/resources/ResourceFragment.kt +++ b/app/src/main/java/com/monstarlab/features/resources/ResourceFragment.kt @@ -2,17 +2,20 @@ package com.monstarlab.features.resources import android.os.Bundle import android.view.View +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels import androidx.transition.TransitionManager import com.google.android.material.snackbar.Snackbar import com.monstarlab.R -import com.monstarlab.arch.base.BaseFragment import com.monstarlab.arch.extensions.collectFlow import com.monstarlab.arch.extensions.viewBinding import com.monstarlab.databinding.FragmentResourceBinding +import dagger.hilt.android.AndroidEntryPoint -class ResourceFragment : BaseFragment(R.layout.fragment_resource) { +@AndroidEntryPoint +class ResourceFragment : Fragment(R.layout.fragment_resource) { - private val viewModel by viewModel() + private val viewModel by viewModels() private val binding by viewBinding(FragmentResourceBinding::bind) private val resourceAdapter = ResourceAdapter() diff --git a/app/src/main/java/com/monstarlab/features/resources/ResourceViewModel.kt b/app/src/main/java/com/monstarlab/features/resources/ResourceViewModel.kt index ee3a6406..fd3be31c 100644 --- a/app/src/main/java/com/monstarlab/features/resources/ResourceViewModel.kt +++ b/app/src/main/java/com/monstarlab/features/resources/ResourceViewModel.kt @@ -8,6 +8,7 @@ import com.monstarlab.core.domain.model.Resource import com.monstarlab.core.sharedui.errorhandling.ViewError import com.monstarlab.core.sharedui.errorhandling.mapToViewError import com.monstarlab.core.usecases.resources.GetResourcesUseCase +import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.launchIn @@ -15,6 +16,7 @@ import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onStart import javax.inject.Inject +@HiltViewModel class ResourceViewModel @Inject constructor( private val getResourcesUseCase: GetResourcesUseCase ) : ViewModel() { diff --git a/app/src/main/java/com/monstarlab/injection/builders/LoginBuilder.kt b/app/src/main/java/com/monstarlab/injection/builders/LoginBuilder.kt deleted file mode 100644 index c8891e59..00000000 --- a/app/src/main/java/com/monstarlab/injection/builders/LoginBuilder.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.monstarlab.injection.builders - -import androidx.lifecycle.ViewModel -import com.monstarlab.features.login.LoginFragment -import com.monstarlab.features.login.LoginViewModel -import com.monstarlab.injection.modules.ViewModelKey -import dagger.Binds -import dagger.Module -import dagger.android.ContributesAndroidInjector -import dagger.multibindings.IntoMap - -@Module -internal abstract class LoginBuilder { - @ContributesAndroidInjector - abstract fun loginFragment(): LoginFragment - - @Binds - @IntoMap - @ViewModelKey(LoginViewModel::class) - internal abstract fun bindLoginViewModel(viewModel: LoginViewModel): ViewModel -} diff --git a/app/src/main/java/com/monstarlab/injection/builders/MainActivityBuilder.kt b/app/src/main/java/com/monstarlab/injection/builders/MainActivityBuilder.kt deleted file mode 100644 index 335b262f..00000000 --- a/app/src/main/java/com/monstarlab/injection/builders/MainActivityBuilder.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.monstarlab.injection.builders - -import com.monstarlab.features.main.MainActivity -import dagger.Module -import dagger.android.ContributesAndroidInjector - -@Module -internal abstract class MainActivityBuilder { - - @ContributesAndroidInjector(modules = []) - internal abstract fun mainActivity(): MainActivity -} diff --git a/app/src/main/java/com/monstarlab/injection/builders/ResourceBuilder.kt b/app/src/main/java/com/monstarlab/injection/builders/ResourceBuilder.kt deleted file mode 100644 index 34b74265..00000000 --- a/app/src/main/java/com/monstarlab/injection/builders/ResourceBuilder.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.monstarlab.injection.builders - -import androidx.lifecycle.ViewModel -import com.monstarlab.features.resources.ResourceFragment -import com.monstarlab.features.resources.ResourceViewModel -import com.monstarlab.injection.modules.ViewModelKey -import dagger.Binds -import dagger.Module -import dagger.android.ContributesAndroidInjector -import dagger.multibindings.IntoMap - -@Module -internal abstract class ResourceBuilder { - @ContributesAndroidInjector - abstract fun sampleFragment(): ResourceFragment - - @Binds - @IntoMap - @ViewModelKey(ResourceViewModel::class) - internal abstract fun bindSampleViewModel(viewModel: ResourceViewModel): ViewModel -} diff --git a/app/src/main/java/com/monstarlab/injection/components/AppComponent.kt b/app/src/main/java/com/monstarlab/injection/components/AppComponent.kt deleted file mode 100644 index d316709b..00000000 --- a/app/src/main/java/com/monstarlab/injection/components/AppComponent.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.monstarlab.injection.components - -import com.monstarlab.App -import com.monstarlab.injection.modules.AppModule -import com.monstarlab.injection.modules.DataModule -import com.monstarlab.injection.modules.InteractorModule -import com.monstarlab.injection.modules.PresentationModule -import com.monstarlab.injection.modules.RestModule -import com.monstarlab.injection.modules.ViewModelBuilder -import dagger.Component -import dagger.android.AndroidInjector -import dagger.android.support.AndroidSupportInjectionModule -import javax.inject.Singleton - -@Component( - modules = [ - AndroidSupportInjectionModule::class, - ViewModelBuilder::class, - PresentationModule::class, - AppModule::class, - InteractorModule::class, - RestModule::class, - DataModule::class - ] -) -@Singleton -interface AppComponent : AndroidInjector { - @Component.Factory - abstract class Factory : AndroidInjector.Factory -} diff --git a/app/src/main/java/com/monstarlab/injection/modules/AppModule.kt b/app/src/main/java/com/monstarlab/injection/modules/AppModule.kt deleted file mode 100644 index 7a28a246..00000000 --- a/app/src/main/java/com/monstarlab/injection/modules/AppModule.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.monstarlab.injection.modules - -import android.content.Context -import com.monstarlab.App -import dagger.Module -import dagger.Provides - -@Module -abstract class AppModule { - - companion object { - @Provides - fun provideContext(application: App): Context = application.applicationContext - } -} diff --git a/app/src/main/java/com/monstarlab/injection/modules/DaggerViewModelFactory.kt b/app/src/main/java/com/monstarlab/injection/modules/DaggerViewModelFactory.kt deleted file mode 100644 index 511e02e0..00000000 --- a/app/src/main/java/com/monstarlab/injection/modules/DaggerViewModelFactory.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.monstarlab.injection.modules - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import javax.inject.Inject -import javax.inject.Provider - -internal class DaggerViewModelFactory @Inject constructor( - private val creators: @JvmSuppressWildcards Map, Provider> -) : ViewModelProvider.Factory { - override fun create(modelClass: Class): T { - var creator: Provider? = creators[modelClass] - if (creator == null) { - for ((key, value) in creators) { - if (modelClass.isAssignableFrom(key)) { - creator = value - break - } - } - } - if (creator == null) { - throw IllegalArgumentException("Unknown model class: $modelClass") - } - try { - @Suppress("UNCHECKED_CAST") - return creator.get() as T - } catch (e: Exception) { - throw RuntimeException(e) - } - } -} diff --git a/app/src/main/java/com/monstarlab/injection/modules/DataModule.kt b/app/src/main/java/com/monstarlab/injection/modules/DataModule.kt index 90ea7f2b..2cbe396c 100644 --- a/app/src/main/java/com/monstarlab/injection/modules/DataModule.kt +++ b/app/src/main/java/com/monstarlab/injection/modules/DataModule.kt @@ -4,12 +4,18 @@ import android.content.Context import android.content.SharedPreferences import dagger.Module import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton +@InstallIn(SingletonComponent::class) @Module class DataModule { + @Singleton @Provides - fun provideSharedPreferences(context: Context): SharedPreferences { + fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences { return context.applicationContext.getSharedPreferences("app_prefs", Context.MODE_PRIVATE) } } diff --git a/app/src/main/java/com/monstarlab/injection/modules/InteractorModule.kt b/app/src/main/java/com/monstarlab/injection/modules/InteractorModule.kt deleted file mode 100644 index a5379179..00000000 --- a/app/src/main/java/com/monstarlab/injection/modules/InteractorModule.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.monstarlab.injection.modules - -import dagger.Module - -@Module -class InteractorModule diff --git a/app/src/main/java/com/monstarlab/injection/modules/PresentationModule.kt b/app/src/main/java/com/monstarlab/injection/modules/PresentationModule.kt deleted file mode 100644 index 0b27980f..00000000 --- a/app/src/main/java/com/monstarlab/injection/modules/PresentationModule.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.monstarlab.injection.modules - -import com.monstarlab.injection.builders.LoginBuilder -import com.monstarlab.injection.builders.MainActivityBuilder -import com.monstarlab.injection.builders.ResourceBuilder -import dagger.Module - -@Module( - includes = [ - MainActivityBuilder::class, - ResourceBuilder::class, - LoginBuilder::class - ] -) -class PresentationModule diff --git a/app/src/main/java/com/monstarlab/injection/modules/RestModule.kt b/app/src/main/java/com/monstarlab/injection/modules/RestModule.kt index 72f50409..47f0fe33 100644 --- a/app/src/main/java/com/monstarlab/injection/modules/RestModule.kt +++ b/app/src/main/java/com/monstarlab/injection/modules/RestModule.kt @@ -5,6 +5,8 @@ import com.monstarlab.BuildConfig import com.monstarlab.core.data.network.Api import dagger.Module import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent import kotlinx.serialization.json.Json import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient @@ -13,6 +15,7 @@ import retrofit2.Retrofit import java.util.concurrent.TimeUnit import javax.inject.Singleton +@InstallIn(SingletonComponent::class) @Module class RestModule { @@ -35,9 +38,7 @@ class RestModule { @Provides @Singleton - fun provideRetrofit( - client: OkHttpClient - ): Retrofit { + fun provideRetrofit(client: OkHttpClient): Retrofit { return Retrofit.Builder() .client(client) .baseUrl(BuildConfig.API_URL) diff --git a/app/src/main/java/com/monstarlab/injection/modules/ViewModelBuilder.kt b/app/src/main/java/com/monstarlab/injection/modules/ViewModelBuilder.kt deleted file mode 100644 index fd106fb3..00000000 --- a/app/src/main/java/com/monstarlab/injection/modules/ViewModelBuilder.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.monstarlab.injection.modules - -import androidx.lifecycle.ViewModelProvider -import dagger.Binds -import dagger.Module - -@Module -abstract class ViewModelBuilder { - - @Binds - internal abstract fun bindViewModelFactory(factory: com.monstarlab.injection.modules.DaggerViewModelFactory): ViewModelProvider.Factory -} diff --git a/app/src/main/java/com/monstarlab/injection/modules/ViewModelKey.kt b/app/src/main/java/com/monstarlab/injection/modules/ViewModelKey.kt deleted file mode 100644 index fa010396..00000000 --- a/app/src/main/java/com/monstarlab/injection/modules/ViewModelKey.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.monstarlab.injection.modules - -import androidx.lifecycle.ViewModel -import dagger.MapKey -import kotlin.reflect.KClass - -@Target( - AnnotationTarget.FUNCTION, - AnnotationTarget.PROPERTY_GETTER, - AnnotationTarget.PROPERTY_SETTER -) -@Retention(AnnotationRetention.RUNTIME) -@MapKey -annotation class ViewModelKey(val value: KClass) diff --git a/build.gradle b/build.gradle index 8f97a4fb..a1325ea0 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,8 @@ buildscript { appcompat : '1.2.0', coroutines : '1.4.2', constraint_layout : '2.0.1', - dagger : '2.30.1', + dagger : '2.33', + hilt : '2.33-beta', lifecycle : '2.3.0', timber : "4.7.1", junit : '4.13.1', @@ -44,6 +45,7 @@ buildscript { classpath "com.android.tools.build:gradle:4.1.2" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}" classpath "dk.nodes.nstack:translation:${versions.nstack_gradle_plugin}" + classpath "com.google.dagger:hilt-android-gradle-plugin:${versions.hilt}" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }