ViewModels的自定义半广义工厂

时间:2017-11-17 09:51:07

标签: android kotlin android-architecture-components android-architecture-lifecycle android-viewmodel

我正在尝试创建一个通用的ViewModelProvider.Factory来实例化我的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.declaredConstructors.size} declaredConstructors")

    modelClass.constructors.forEach {
        Log.d("Factory", "Constructor: $it")
    }
    return when {
        AppViewModel::class.java.isAssignableFrom(modelClass)               -> modelClass.getDeclaredConstructor(AppParameterBundle::class.java).newInstance(bundle)
        AppTeamUserViewModel::class.java.isAssignableFrom(modelClass)       -> modelClass.getDeclaredConstructor(AppTeamUserParameterBundle::class.java).newInstance(bundle)
        AppTeamUserHuntIdViewModel::class.java.isAssignableFrom(modelClass) -> modelClass.getDeclaredConstructor(AppTeamUserHuntIdParameterBundle::class.java).newInstance(bundle)
        AppStringViewModel::class.java.isAssignableFrom(modelClass)         -> modelClass.getDeclaredConstructor(AppStringParameterBundle::class.java).newInstance(bundle)
        else                                                                -> super.create(modelClass)
    }
}
}

这些是我的捆绑包:

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)

这些是我使用自定义ViewModel扩展的基本ViewModel:

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)

从其中一个扩展的ViewModel示例:

class TeamViewModel(bundle: AppParameterBundle) : AppViewModel<TeamUiModel, TeamEvent>(bundle) {
...
}

我的问题是

modelClass.getDeclaredConstructor(AppParameterBundle::class.java).newInstance(bundle) 

找不到任何构造函数和这行

Log.d("Factory", "${modelClass.canonicalName} has ${modelClass.constructors.size} constructors and ${modelClass.declaredConstructors.size} declaredConstructors")

在日志中出现

mypackage.viewmodels.TeamViewModel has 0 constructors and 0 declaredConstructors

这是我在stacktrace中得到的:

Caused by: java.lang.NoSuchMethodException: <init> [class mypackage.ParameterBundle]
                                                   at java.lang.Class.getConstructor(Class.java:528)
                                                   at java.lang.Class.getDeclaredConstructor(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)

这是一个没有构造函数的Kotlin问题吗?我该如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

这是一个Proguard问题。 我不得不将这些行添加到.pro规则文件

-keep class mypackage.** { *; }

-keepclassmembers public class mypackage.** { *; }