Fábrica semi-generalizada personalizada para ViewModels
Intento crear un ViewModelProvider.Factory generalizado para instanciar mis ViewModels
class BundledAppFactory(private var bundle: AppParameterBundle) : ViewModelProvider.NewInstanceFactory() { override fun <T : ViewModel> create(modelClass: Class<T>): T { Log.d("Factory", "Creating ${modelClass.canonicalName}") Log.d("Factory", "${modelClass.canonicalName} has ${modelClass.constructors.size} constructors and ${modelClass.declanetworkingConstructors.size} declanetworkingConstructors") modelClass.constructors.forEach { Log.d("Factory", "Constructor: $it") } return when { AppViewModel::class.java.isAssignableFrom(modelClass) -> modelClass.getDeclanetworkingConstructor(AppParameterBundle::class.java).newInstance(bundle) AppTeamUserViewModel::class.java.isAssignableFrom(modelClass) -> modelClass.getDeclanetworkingConstructor(AppTeamUserParameterBundle::class.java).newInstance(bundle) AppTeamUserHuntIdViewModel::class.java.isAssignableFrom(modelClass) -> modelClass.getDeclanetworkingConstructor(AppTeamUserHuntIdParameterBundle::class.java).newInstance(bundle) AppStringViewModel::class.java.isAssignableFrom(modelClass) -> modelClass.getDeclanetworkingConstructor(AppStringParameterBundle::class.java).newInstance(bundle) else -> super.create(modelClass) } } }
Estos son mis packages:
- Obtenga una date de un DatePickerDialog en Kotlin Android
- RxJava manejando múltiples devoluciones de llamada dentro de un observable
- Kotlin - Diferencia entre el bucle "forEachIndexed" y "for in"
- function parámetro tipo coinciden problema
- Cómo usar kapt desde la línea de command (con kotlinc)?
open class AppParameterBundle(val application: Application) class AppStringParameterBundle(app: Application, val string: String) : AppParameterBundle(app) class AppTeamUserParameterBundle(app: Application, val team: Team, val user: User) : AppParameterBundle(app) class AppTeamUserHuntIdParameterBundle(app: Application, val huntId: String, val team: Team, val user: User) : AppParameterBundle(app)
Y estos son los ViewModels de base que amplío con ViewModels personalizados:
abstract class AppViewModel<MODEL, EVENT : Any>(bundle: AppParameterBundle) : BaseViewModel<MODEL, EVENT>(bundle) abstract class AppTeamUserViewModel<MODEL, EVENT : Any>(bundle: AppTeamUserParameterBundle) : BaseViewModel<MODEL, EVENT>(bundle) abstract class AppTeamUserHuntIdViewModel<MODEL, EVENT : Any>(bundle: AppTeamUserHuntIdParameterBundle) : BaseViewModel<MODEL, EVENT>(bundle) abstract class AppStringViewModel<MODEL, EVENT : Any>(bundle: AppStringParameterBundle) : BaseViewModel<MODEL, EVENT>(bundle)
Y un ejemplo de un ViewModel que se extiende desde uno de estos:
class TeamViewModel(bundle: AppParameterBundle) : AppViewModel<TeamUiModel, TeamEvent>(bundle) { ... }
Mi problema es que
modelClass.getDeclanetworkingConstructor(AppParameterBundle::class.java).newInstance(bundle)
no encontrará ningún constructor y estas líneas
Log.d("Factory", "${modelClass.canonicalName} has ${modelClass.constructors.size} constructors and ${modelClass.declanetworkingConstructors.size} declanetworkingConstructors")
aparece como esto en los loggings
mypackage.viewmodels.TeamViewModel has 0 constructors and 0 declanetworkingConstructors
Esto es lo que obtengo en stacktrace:
Caused by: java.lang.NoSuchMethodException: <init> [class mypackage.ParameterBundle] at java.lang.Class.getConstructor(Class.java:528) at java.lang.Class.getDeclanetworkingConstructor(Class.java:507) at mypackage.viewmodels.BundledAppFactory.create(FactoriesAndBundles.kt:39) at android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:128) at mypackage.TeamActivity.onCreate(TeamActivity.kt:41)
¿Es esto un problema de Kotlin que no hay constructores? ¿Cómo puedo solucionar esto?
- ¿Por qué Smart-Cast no maneja esta situación?
- Kotlin - getPendingIntent con syntax de múltiples indicadores
- ¿Es posible aplicar una sola anotación a múltiples objectives de sitio de uso en Kotlin?
- Val y Var en Kotlin
- El logcat de Android Studio sigue funcionando
- ¿Por qué Kotlin con Spring MVC JSON devuelve un object vacío?
- Android: ¿cómo lograr setOnClickListener en Kotlin?
- ¿Cómo inyectar en var en Kotlin?
Fue un problema de Proguard. Tuve que agregar estas líneas al file de reglas .pro
-keep class mypackage.** { *; } -keepclassmembers public class mypackage.** { *; }