StackOverflowError on ViewModel initialization



我在 ViewModel 类初始化期间遇到了奇怪的问题。我想代码是解释问题的最佳方式。

我的所有视图模型都是在此之后继承的:

abstract class BaseViewModel : ViewModel() {
internal var args: Bundle? = null
}

我委托将视图模型提供给片段,它会自动从片段加载参数。

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.StackOverflowError: 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属性。 即方法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上设置参数

相关内容

  • 没有找到相关文章

最新更新