我正在实现一个应用程序的空状态屏幕,但它在第二次返回片段后崩溃。
当应用程序第一次启动时,它正确地创建了我的视图,但当我向以前的列表添加一些东西时(主片段-〉注册文档片段(为我的回收列表创建新项目)-〉主片段),它在下面的行中崩溃:
binding.imageEmptyState.hide()
从以下函数:
private fun configDataCollector() = lifecycleScope.launch {
viewModel.list.collectLatest { result->
when(result) {
is ResourceState.Success -> {
binding.imageEmptyState.hide()
binding.textEmptyState.hide()
result.data?.let { values ->
adapterDoc.docs = values.toList()
}
}
is ResourceState.Empty -> {
binding.imageEmptyState.show()
binding.textEmptyState.show()
}
else -> { }
}
}
}
收货:
2023-01-04 11:55:35.905 14014-14014/com.tods.docreminder E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.tods.docreminder, PID: 14014
java.lang.NullPointerException
at com.tods.docreminder.feature.doc.presentation.util.BaseFragment.getBinding(BaseFragment.kt:13)
at com.tods.docreminder.feature.doc.presentation.doc.MainFragment.access$getBinding(MainFragment.kt:34)
at com.tods.docreminder.feature.doc.presentation.doc.MainFragment$configDataCollector$1$1.invokeSuspend(MainFragment.kt:255)
我的资源状态类:
sealed class ResourceState<T>(
val data: T? = null,
val message: String? = null
) {
class Success<T>(data: T?): ResourceState<T>(data)
class Error<T>(message: String?, data: T? = null): ResourceState<T>(data, message)
class Loading<T>: ResourceState<T>()
class Empty<T>: ResourceState<T>()
}
碱基片段:
abstract class BaseFragment<VB: ViewBinding, VM: ViewModel>: Fragment() {
private var _binding: VB? = null
protected val binding get() = _binding!!
protected abstract val viewModel: VM
override fun onCreateView
(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = recoverViewBinding(inflater, container)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
protected abstract fun recoverViewBinding(inflater: LayoutInflater, container: ViewGroup?): VB
}
为什么会发生在这种情况下?
谢谢你的帮助,如果需要任何其他代码,我会尽快编辑的问题。
1条答案
按热度按时间0md85ypi1#
Fragment示例的生命周期比其视图的生命周期长。如下所示,这些函数表示开始和停止的生命周期。在Fragment的生命周期仍在运行时,可以多次创建和销毁视图。
因此,如果你在一个协程中引用
binding
,而这个协程位于Fragment的lifecycleScope
上,而不是位于viewLifecycle
的lifecycleScope
上,那么你的协程就有可能在binding
为空时尝试使用它,此时:如果你使用
viewlifecycle.lifecycleScope
作为你的协程,当视图被销毁时,它会自动被取消,所以在Fragment的生命周期中,它永远不会尝试在这些无效的时间使用binding
。这是一个观点的问题,但我想指出的是,我认为BaseFragments引起的问题比它们解决的问题更多。
由于Kotlin具有扩展函数和属性委托,因此您可以获得相同的好处,而不会遇到上面文章中提到的所有问题。