mnawrot
11/13/2017, 12:37 PMBaseViewModelFactory<VM>
class to provide new architecture component's view models.
i wanted to call isAssignable(...)
function before i create actual viewmodel, to check if everything is fine, but in order to do that, the viewmodel type VM
have to be reified and i dont know how to call inline reified function from overriden ViewModelProviders.Factory create()
function
currently i got something like this :
abstract class BaseViewModelFactory<out VM : Any>(private val viewModelClass: KClass<VM>) : ViewModelProvider.Factory {
@Suppress("unchecked_cast")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
require(modelClass.isAssignableFrom(viewModelClass.java)) {
"Could not instantiate ${javaClass.simpleName} class"
}
return createViewModel() as T
}
abstract protected fun createViewModel(): VM
}
is there a way to avoid passing viewModelClass in constructor and somehow use reified type parameter here?leosan
11/13/2017, 1:31 PMmnawrot
11/13/2017, 1:56 PMyperess
11/13/2017, 8:08 PM@Singleton
class MetaverseViewModelFactory @Inject constructor(
creators: Map<KClass<out ViewModel>, Provider<ViewModel>>
): ViewModelProvider.Factory {
private val creators: Map<Class<out ViewModel>, Provider<ViewModel>> =
creators.mapKeys { it.key.java }
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
Log.d("ViewModelFactory", "create($modelClass)")
var creator = creators[modelClass]
if (creator == null) {
creators.entries.forEach { entry ->
if (modelClass.isAssignableFrom(entry.key)) {
creator = entry.value
return@forEach
}
}
}
if (creator == null) {
throw IllegalArgumentException("Unknown model class $modelClass")
}
try {
return creator!!.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
@Module
abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(MainViewModel::class)
abstract fun bindMainViewModel(mainViewModel: MainViewModel): ViewModel
@Binds
abstract fun bindViewModelFactory(factory: MetaverseViewModelFactory): ViewModelProvider.Factory
}
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
rkeazor
11/14/2017, 9:52 AMmnawrot
11/15/2017, 8:47 AMyperess
11/15/2017, 12:01 PM