¿Cómo puedo poner en práctica una ViewModelFactory
de proporcionar mi proyecto ViewModels
y sus dependencias para todo el proyecto?
Bueno, hay uno llamado GithubBrowser y pero no es un tutorial, se trata de un proyecto. Usted debe saber daga para android para hacer eso. O bien, puede comprobar el código de abajo:
@Singleton
class DaggerViewModelFactory @Inject constructor(
private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
val creator = creators[modelClass] ?: creators.entries.firstOrNull {
modelClass.isAssignableFrom(it.key)
}?.value ?: throw IllegalArgumentException("unknown model class $modelClass")
try {
@Suppress("UNCHECKED_CAST")
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
Esta parte se creará un modelo de vista "genérico" para toda la aplicación. De esa manera, el ViewModel
se crea con argumentos ASIGNADA. Después de que es necesario implementar el módulo de fábrica en sus módulos de Singleton, y su inclusión en el componente.
@Component(
modules = [... ViewModelModule::class]
)
interface AppCompoenent{}
Ahora la parte divertida:
@Suppress("unused")
@Module
abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(MyViewModel::class)
abstract fun bindsMyViewModel(viewModel: MyViewModel): ViewModel
@Binds
abstract fun bindsViewModelFactory(factory: DaggerViewModelFactory): ViewModelProvider.Factory
}
Desde daga unión múltiple apoyo que están libres de unirse como mayo ViewModels
como desee.
El ViewModelKey:
@Target(
AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
Que son básicamente Puting valores en un HashMap. Estos valores son su ViewModel
.
Acumulación Hit! Done.After que acaba de inyectar una ViewModelProvider.Facory
en su fragmento. Que en el ViewModel
que puede hacer:
class MyViewModel @Inject constructor(
private val dependency: YourDependency
) : ViewModel() {}
Para dejar en claro lo que solicitó a los comentarios. En primer lugar, no hay necesidad específica de saber lo que está sucediendo dentro de la DaggerViewModelFactory
, aunque no recomiendo el aprendizaje de esta manera porque soy un ventilador fuerte de "siempre saber lo que está pasando". FYI el DaggerViewModelFactory
es sólo una clase que acepta una Map
con cada clase que se extiende ViewModel
como una llave, y que las dependencias de la clase como un valor. Cuando se usa Provider<T>
la daga sabe cómo encontrar esas dependencias, pero todavía no los lleva a que, hasta que haya llamado provider.get()
. Piense en ello como una simple inicialización perezosa.
Ahora comprobar el modelClass.isAssignableFrom(it.key)
. Es sólo comprueba si esa clase realmente se extiende ViewModel
.
En cuanto a su segunda pregunta, es importante entender la primera parte. Dado que Dagger
los soportes de unión múltiple, lo que significa que pueden proporcionar las dependencias utilizando una Map<Key, Value>
. Por ejemplo, una Map<HomeViewModel, Provider<ViewModel>>
será básicamente decirle daga que me dan HomeViewModel
's dependencias. Daga va a decir: ¿Cómo saber cuáles son HomeViewModel
las dependencias? Y responde: Ya he definido una clave para que y es la HomeViewModel
clase misma. Por lo que acaba de crear una anotación, combinarlo con @Binds
y @IntoMap
, y en el fondo de la daga se acaba de realizar una map.put(HomeViewModel::class, AndDependencies)
.