Android Kotlin中Fragment使用activityViewModels委托ViewModel报错
问题:Fragment中使用activityViewModels委托ViewModel编译报错
场景还原
在Android Kotlin开发中,Fragment里尝试用委托语法通过activityViewModels<>()获取ViewModel:
val viewModel:NewsViewModel by activityViewModels<> { }
触发编译错误:
Property delegate must have a 'getValue(BreakingNews, KProperty*>)' method. None of the following functions are suitable. Lazy<NewsViewModel>.getValue(Any?, KProperty<*>) where T = NewsViewModel for inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T defined in kotlin
但在MainActivity中,手动通过ViewModelProvider实例化ViewModel却完全正常:
val viewmodelFactory = ViewModelProviderFactory(dataRepo) viewModel = ViewModelProvider(this,viewmodelFactory).get(NewsViewModel::class.java)
相关代码片段
ViewModel工厂类
class ViewModelProviderFactory(val Repo:NewsRepository): ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>,extras: CreationExtras): T { return NewsViewModel(Repo) as T } }
ViewModel核心属性
var breakingNews: MutableLiveData<Resource<ArticleList>> = MutableLiveData() var breakingNewsPage = 1 var breakingNewsResponse: ArticleList? = null var searchNews: MutableLiveData<Resource<ArticleList>> = MutableLiveData() var searchNewsPage = 1 var searchNewsResponse: ArticleList? = null var savedNumerics = 0 var _status = MutableLiveData<String>() // 其余代码省略
修复方案
这个错误本质是委托属性的类型匹配失败,activityViewModels()要求传入的工厂返回的ViewModel类型与委托声明的类型完全兼容,同时要确保工厂实现正确、委托时传递合法的工厂实例。
具体修复步骤:
- 不要留空lambda,在
activityViewModels中传入你的工厂实例(注意要传入和Activity中一致的NewsRepository实例):val viewModel: NewsViewModel by activityViewModels { ViewModelProviderFactory(dataRepo) } - 优化工厂类的类型转换逻辑,避免不安全的强制转换,添加类型校验:
class ViewModelProviderFactory(val repo: NewsRepository) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T { return if (modelClass.isAssignableFrom(NewsViewModel::class.java)) { NewsViewModel(repo) as T } else { throw IllegalArgumentException("未知ViewModel类:${modelClass.name}") } } } - 确认
NewsViewModel的构造函数只有接收NewsRepository这一种重载,避免因构造函数不匹配导致的类型异常。
完成以上修改后,委托属性就能正确匹配getValue方法,编译报错即可解决。
内容的提问来源于stack exchange,提问作者Theprogrammingnoob
相关产品推荐
相关产品推荐

