DialogFragment中无法访问ViewModel的问题排查
问题原因
错误java.lang.IllegalStateException: Can't access ViewModels from detached fragment的核心原因是:你在CalenderFragment的构造阶段就初始化了ViewModel,此时Fragment还未关联到Activity(处于detached状态),无法访问ViewModelStore,导致抛出异常。
解决方案
有两种可靠的修改方式,推荐使用第一种:
方式一:使用Kotlin委托属性(推荐)
利用Jetpack提供的by viewModels()委托,它会自动在Fragment合适的生命周期(已attach到Activity)初始化ViewModel,无需手动管理时机:
class CalenderFragment : DialogFragment() { // 使用by viewModels()委托自动初始化ViewModel private val viewModel: DViewModel by viewModels() private fun setMonthView() { val calenderHighlighter = CalenderHighlighter() val month = MonthSeperator(selectedDate!!)!!.toInt() val year = YearSeperator(selectedDate!!)!!.toInt() calenderHighlighter.positionsList(viewModel.retrivePositions(month, year)) } // 其他必要的生命周期方法... }
方式二:手动在生命周期方法中初始化
如果不使用委托,可以在Fragment已attach后的生命周期方法(比如onViewCreated或onAttach)中初始化ViewModel:
class CalenderFragment : DialogFragment() { private lateinit var viewModel: DViewModel override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // Fragment已关联视图,此时可安全获取ViewModel viewModel = ViewModelProvider(this).get(DViewModel::class.java) } private fun setMonthView() { val calenderHighlighter = CalenderHighlighter() val month = MonthSeperator(selectedDate!!)!!.toInt() val year = YearSeperator(selectedDate!!)!!.toInt() calenderHighlighter.positionsList(viewModel.retrivePositions(month, year)) } }
说明
两种方式都能确保ViewModel在Fragment处于attached状态时被初始化,避免访问ViewModelStore时的异常。by viewModels()是官方推荐的写法,代码更简洁且不易出错。
内容的提问来源于stack exchange,提问作者Kiran Kittu
相关产品推荐
相关产品推荐

