Skip to content

Instantly share code, notes, and snippets.

@truedem
Last active December 14, 2020 13:20
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save truedem/e5b0c6e161358b88195a24757636ff70 to your computer and use it in GitHub Desktop.
Save truedem/e5b0c6e161358b88195a24757636ff70 to your computer and use it in GitHub Desktop.
ViewModelFactory for Android Jetpack
class ViewModelFactory constructor(
private val baseRepository: BaseRepository, // your repository class to handle database, network, shared preferences, etc.
owner: SavedStateRegistryOwner,
defaultArgs: Bundle? = null
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
// usage in activity:
// val sharedVM by viewModels<MySharedViewModel> { ViewModelFactory(App.getRep(), this) }
// App.getRep() returns instance of BaseRepository, replace with your actual logic
// usage in fragment:
// private val sharedVM: MySharedViewModel by activityViewModels()
// private val viewModel by viewModels<ViewModelHistory> { getViewModelFactory() }
// usage in ViewModels:
// class ViewModelHistory(repository: BaseRepository) : ViewModel(), VMRepository {
// class ViewModelHistoryState(repository: BaseRepository, state: SavedStateHandle) : ViewModel(), VMRepositoryState {
override fun <T : ViewModel> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
) = with(modelClass.interfaces) {
when {
contains(VMRepository::class.java) ->
modelClass
.getConstructor(BaseRepository::class.java)
.newInstance(baseRepository)
contains(VMRepositoryState::class.java) ->
modelClass
.getConstructor(BaseRepository::class.java, SavedStateHandle::class.java)
.newInstance(baseRepository, handle)
else ->
throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")
}
} as T
}
fun Fragment.getViewModelFactory(): ViewModelFactory {
// val repository = (requireContext().applicationContext as App).getRepository()
return ViewModelFactory(App.getRep(), this, arguments) // App.getRep() returns instance of BaseRepository, replace with your actual logic
}
interface VMRepository
interface VMRepositoryState
@truedem
Copy link
Author

truedem commented Dec 12, 2020

Unfortunately this code (reflexions) doesn't work with Proguard/R8 so you'll have to exclude viewmodels from the obfuscation using these Proguard rules:

-keepclasseswithmembers class * {
public <init>(app.acom.mypackage.BaseRepository);
}

-keepclasseswithmembers class * {
public <init>(app.acom.mypackage.BaseRepository, androidx.lifecycle.SavedStateHandle);
}

Alternative would be this code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment