ViewModel 初始化时发生 StackOverflowError
StackOverflowError on ViewModel initialization
我在 ViewModel class 初始化期间遇到了一个奇怪的问题。我想代码是解释问题的最佳方式。
我所有的 ViewModels 都是在这之后继承的:
abstract class BaseViewModel : ViewModel() {
internal var args: Bundle? = null
}
我有委托为片段提供 ViewModel,它会自动从片段加载参数。
interface ViewModelFactoryProvider<VIEW_MODEL : BaseViewModel, BINDING : ViewDataBinding> : ReadOnlyProperty<ViewModelFragment<VIEW_MODEL, BINDING>, VIEW_MODEL> {
val viewModelFactory: ViewModelProvider.Factory
override fun getValue(thisRef: ViewModelFragment<VIEW_MODEL, BINDING>, property: KProperty<*>): VIEW_MODEL {
return ViewModelProviders.of(thisRef, viewModelFactory).get(thisRef.viewModelClass).apply {
thisRef.arguments?.let { thisRef.viewModel.args = it }
}
}
}
基础片段实现上面的接口并以这种方式创建视图模型:
class ViewModelFragment<VIEW_MODEL : BaseViewModel, BINDING : ViewDataBinding> : Fragment(), ViewModelFactoryProvider<VIEW_MODEL, BINDING>{
@Inject
override lateinit var viewModelFactory: ViewModelProvider.Factory
val viewModel: VIEW_MODEL by this
}
一切正常,直到我的 ViewModel 的片段没有任何额外的参数,否则我得到:
java.lang.WhosebugError: stack size 8MB
at android.support.v4.app.Fragment.getContext(Fragment.java:683)
at android.support.v4.app.Fragment.getViewModelStore(Fragment.java:327)
at android.arch.lifecycle.ViewModelStores.of(ViewModelStores.java:60)
at android.arch.lifecycle.ViewModelProviders.of(ViewModelProviders.java:104)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:15)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$
现在我不知道在哪里可以搜索循环依赖以及它的原因是什么。请帮忙
这是由于在委托
中计算它的值时访问 thisRef.viewModel
造成的
您通过 by this
委托 viewModel
属性。 IE。方法 getViewModel()
使用委托的 override fun getValue(..)
方法,后者又调用 thisRef.viewModel.args = it
中的 getViewModel()
。圆在那个点重新开始。
你要的大概是
override fun getValue(thisRef: ViewModelFragment<VIEW_MODEL, BINDING>, property: KProperty<*>): VIEW_MODEL {
return ViewModelProviders.of(thisRef, viewModelFactory).get(thisRef.viewModelClass).apply {
thisRef.arguments?.let { this.args = it }
}
}
}
它不在它试图创建的 属性 上设置参数,而是在从 ViewModelProviders.of(...).get(...)
返回的 ViewModel
上设置参数
我在 ViewModel class 初始化期间遇到了一个奇怪的问题。我想代码是解释问题的最佳方式。
我所有的 ViewModels 都是在这之后继承的:
abstract class BaseViewModel : ViewModel() {
internal var args: Bundle? = null
}
我有委托为片段提供 ViewModel,它会自动从片段加载参数。
interface ViewModelFactoryProvider<VIEW_MODEL : BaseViewModel, BINDING : ViewDataBinding> : ReadOnlyProperty<ViewModelFragment<VIEW_MODEL, BINDING>, VIEW_MODEL> {
val viewModelFactory: ViewModelProvider.Factory
override fun getValue(thisRef: ViewModelFragment<VIEW_MODEL, BINDING>, property: KProperty<*>): VIEW_MODEL {
return ViewModelProviders.of(thisRef, viewModelFactory).get(thisRef.viewModelClass).apply {
thisRef.arguments?.let { thisRef.viewModel.args = it }
}
}
}
基础片段实现上面的接口并以这种方式创建视图模型:
class ViewModelFragment<VIEW_MODEL : BaseViewModel, BINDING : ViewDataBinding> : Fragment(), ViewModelFactoryProvider<VIEW_MODEL, BINDING>{
@Inject
override lateinit var viewModelFactory: ViewModelProvider.Factory
val viewModel: VIEW_MODEL by this
}
一切正常,直到我的 ViewModel 的片段没有任何额外的参数,否则我得到:
java.lang.WhosebugError: stack size 8MB
at android.support.v4.app.Fragment.getContext(Fragment.java:683)
at android.support.v4.app.Fragment.getViewModelStore(Fragment.java:327)
at android.arch.lifecycle.ViewModelStores.of(ViewModelStores.java:60)
at android.arch.lifecycle.ViewModelProviders.of(ViewModelProviders.java:104)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:15)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$DefaultImpls.getValue(ViewModelFactoryProvider.kt:16)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getValue(ViewModelFragment.kt:20)
at pl.kulbaka.karol.unilang.tools.ViewModelFragment.getViewModel(ViewModelFragment.kt)
at pl.kulbaka.karol.unilang.tools.viewmodel.ViewModelFactoryProvider$
现在我不知道在哪里可以搜索循环依赖以及它的原因是什么。请帮忙
这是由于在委托
中计算它的值时访问thisRef.viewModel
造成的
您通过 by this
委托 viewModel
属性。 IE。方法 getViewModel()
使用委托的 override fun getValue(..)
方法,后者又调用 thisRef.viewModel.args = it
中的 getViewModel()
。圆在那个点重新开始。
你要的大概是
override fun getValue(thisRef: ViewModelFragment<VIEW_MODEL, BINDING>, property: KProperty<*>): VIEW_MODEL {
return ViewModelProviders.of(thisRef, viewModelFactory).get(thisRef.viewModelClass).apply {
thisRef.arguments?.let { this.args = it }
}
}
}
它不在它试图创建的 属性 上设置参数,而是在从 ViewModelProviders.of(...).get(...)
ViewModel
上设置参数