From c1c36adb0b320027ba99fb8167cb5d6d194543d0 Mon Sep 17 00:00:00 2001 From: Alex Dochioiu Date: Mon, 26 Oct 2020 17:46:55 +0000 Subject: [PATCH] Improved the ViewModelProvider Factory to require less boilerplate --- .../android/example/github/di/AppModule.kt | 2 +- .../android/example/github/di/ViewModelKey.kt | 31 ----------- .../example/github/di/ViewModelModule.kt | 51 ------------------- .../example/github/ui/repo/RepoFragment.kt | 4 +- .../github/ui/search/SearchFragment.kt | 4 +- .../example/github/ui/user/UserFragment.kt | 3 +- .../viewmodel/GithubViewModelFactory.kt | 17 ++----- 7 files changed, 12 insertions(+), 100 deletions(-) delete mode 100644 GithubBrowserSample/app/src/main/java/com/android/example/github/di/ViewModelKey.kt delete mode 100644 GithubBrowserSample/app/src/main/java/com/android/example/github/di/ViewModelModule.kt diff --git a/GithubBrowserSample/app/src/main/java/com/android/example/github/di/AppModule.kt b/GithubBrowserSample/app/src/main/java/com/android/example/github/di/AppModule.kt index ade8ae81..a4cebcd1 100644 --- a/GithubBrowserSample/app/src/main/java/com/android/example/github/di/AppModule.kt +++ b/GithubBrowserSample/app/src/main/java/com/android/example/github/di/AppModule.kt @@ -29,7 +29,7 @@ import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import javax.inject.Singleton -@Module(includes = [ViewModelModule::class]) +@Module class AppModule { @Singleton @Provides diff --git a/GithubBrowserSample/app/src/main/java/com/android/example/github/di/ViewModelKey.kt b/GithubBrowserSample/app/src/main/java/com/android/example/github/di/ViewModelKey.kt deleted file mode 100644 index 02f94870..00000000 --- a/GithubBrowserSample/app/src/main/java/com/android/example/github/di/ViewModelKey.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.example.github.di - -import androidx.lifecycle.ViewModel -import dagger.MapKey -import kotlin.reflect.KClass - -@MustBeDocumented -@Target( - AnnotationTarget.FUNCTION, - AnnotationTarget.PROPERTY_GETTER, - AnnotationTarget.PROPERTY_SETTER -) -@Retention(AnnotationRetention.RUNTIME) -@MapKey -annotation class ViewModelKey(val value: KClass) diff --git a/GithubBrowserSample/app/src/main/java/com/android/example/github/di/ViewModelModule.kt b/GithubBrowserSample/app/src/main/java/com/android/example/github/di/ViewModelModule.kt deleted file mode 100644 index 44f42699..00000000 --- a/GithubBrowserSample/app/src/main/java/com/android/example/github/di/ViewModelModule.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.example.github.di - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider - -import com.android.example.github.ui.repo.RepoViewModel -import com.android.example.github.ui.search.SearchViewModel -import com.android.example.github.ui.user.UserViewModel -import com.android.example.github.viewmodel.GithubViewModelFactory - -import dagger.Binds -import dagger.Module -import dagger.multibindings.IntoMap - -@Suppress("unused") -@Module -abstract class ViewModelModule { - @Binds - @IntoMap - @ViewModelKey(UserViewModel::class) - abstract fun bindUserViewModel(userViewModel: UserViewModel): ViewModel - - @Binds - @IntoMap - @ViewModelKey(SearchViewModel::class) - abstract fun bindSearchViewModel(searchViewModel: SearchViewModel): ViewModel - - @Binds - @IntoMap - @ViewModelKey(RepoViewModel::class) - abstract fun bindRepoViewModel(repoViewModel: RepoViewModel): ViewModel - - @Binds - abstract fun bindViewModelFactory(factory: GithubViewModelFactory): ViewModelProvider.Factory -} diff --git a/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/repo/RepoFragment.kt b/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/repo/RepoFragment.kt index 59c43b0c..1ca01323 100644 --- a/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/repo/RepoFragment.kt +++ b/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/repo/RepoFragment.kt @@ -26,7 +26,6 @@ import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.Observer -import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.FragmentNavigatorExtras import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs @@ -38,6 +37,7 @@ import com.android.example.github.databinding.RepoFragmentBinding import com.android.example.github.di.Injectable import com.android.example.github.ui.common.RetryCallback import com.android.example.github.util.autoCleared +import com.android.example.github.viewmodel.GithubViewModelFactory import javax.inject.Inject /** @@ -46,7 +46,7 @@ import javax.inject.Inject class RepoFragment : Fragment(), Injectable { @Inject - lateinit var viewModelFactory: ViewModelProvider.Factory + lateinit var viewModelFactory: GithubViewModelFactory val repoViewModel: RepoViewModel by viewModels { viewModelFactory diff --git a/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/search/SearchFragment.kt b/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/search/SearchFragment.kt index 1a6bbe43..3b5308f6 100644 --- a/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/search/SearchFragment.kt +++ b/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/search/SearchFragment.kt @@ -30,7 +30,6 @@ import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.Observer -import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -42,13 +41,14 @@ import com.android.example.github.di.Injectable import com.android.example.github.ui.common.RepoListAdapter import com.android.example.github.ui.common.RetryCallback import com.android.example.github.util.autoCleared +import com.android.example.github.viewmodel.GithubViewModelFactory import com.google.android.material.snackbar.Snackbar import javax.inject.Inject class SearchFragment : Fragment(), Injectable { @Inject - lateinit var viewModelFactory: ViewModelProvider.Factory + lateinit var viewModelFactory: GithubViewModelFactory @Inject lateinit var appExecutors: AppExecutors diff --git a/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/user/UserFragment.kt b/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/user/UserFragment.kt index 6cff9c35..01f99a95 100644 --- a/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/user/UserFragment.kt +++ b/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/user/UserFragment.kt @@ -38,6 +38,7 @@ import com.android.example.github.di.Injectable import com.android.example.github.ui.common.RepoListAdapter import com.android.example.github.ui.common.RetryCallback import com.android.example.github.util.autoCleared +import com.android.example.github.viewmodel.GithubViewModelFactory import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.request.RequestListener @@ -47,7 +48,7 @@ import javax.inject.Inject class UserFragment : Fragment(), Injectable { @Inject - lateinit var viewModelFactory: ViewModelProvider.Factory + lateinit var viewModelFactory: GithubViewModelFactory @Inject lateinit var appExecutors: AppExecutors diff --git a/GithubBrowserSample/app/src/main/java/com/android/example/github/viewmodel/GithubViewModelFactory.kt b/GithubBrowserSample/app/src/main/java/com/android/example/github/viewmodel/GithubViewModelFactory.kt index a068e368..ed32a1da 100644 --- a/GithubBrowserSample/app/src/main/java/com/android/example/github/viewmodel/GithubViewModelFactory.kt +++ b/GithubBrowserSample/app/src/main/java/com/android/example/github/viewmodel/GithubViewModelFactory.kt @@ -18,20 +18,13 @@ package com.android.example.github.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider - import javax.inject.Inject import javax.inject.Provider -import javax.inject.Singleton -@Singleton -class GithubViewModelFactory @Inject constructor( - private val creators: Map, @JvmSuppressWildcards Provider> +class GithubViewModelFactory @Inject constructor( + private val vmProvider: Provider ) : ViewModelProvider.Factory { - override fun create(modelClass: Class): T { - val creator = creators[modelClass] ?: creators.entries.firstOrNull { - modelClass.isAssignableFrom(it.key) - }?.value ?: throw IllegalArgumentException("unknown model class $modelClass") - @Suppress("UNCHECKED_CAST") - return creator.get() as T - } + + @Suppress("UNCHECKED_CAST") + override fun create(modelClass: Class): T = vmProvider.get() as T }