Android fragment DataBinding nonnull getter 返回 null

Android fragment DataBinding nonnull getter return null

提问人:Moti 提问时间:6/16/2022 更新时间:6/17/2022 访问量:352

问:

根据 android 文档,为了获取片段中的数据绑定,我使用了一个不可为 null 的 getter,但有时当我尝试再次访问它时,在我等待用户执行某些操作后,我会收到一个 .NullPointerException

private var _binding: ResultProfileBinding? = null

private val binding get() = _binding!!

override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,
    savedInstanceState: Bundle?): View? {

    _binding = ResultProfileBinding.inflate(inflater)
    return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
   super.onViewCreated(view, savedInstanceState)

   setupViews()
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

private fun setupViews() {
   
   // On click listener initialized right after view created, all is well so far.
   binding.btnCheckResult.setOnClickListener {

      // There is the crash when trying to get the nonnull binding.
      binding.isLoading = true

   }
}

有谁知道NullPointerException崩溃的原因是什么?我试图避免不按照android文档工作,并且不要返回使用可为空的绑定属性(例如)。还有别的办法吗?_binding?.isLoading

android kotlin android-fragments 数据绑定 nullpointerexception

评论

0赞 Tenfour04 6/16/2022
这是您正在使用的确切代码,还是在发布之前删除了一些内容以简化它。上面的代码看起来很安全。视图的点击侦听器只能在屏幕上时调用,这在逻辑上必须在被调用之前调用。顺便说一句,ViewBinding 和 DataBinding 并不完全相同。您的问题涉及 DataBinding,但您链接了 ViewBinding 的文档。但是,在 Fragment 中导入它们的方式可以采用相同的方式。onDestroyView()
0赞 Moti 6/16/2022
是的,这是完全相同的代码,我注意到文档是针对 ViewBinding 的,但我想就像你说的,它应该与 DataBinding 相同。

答:

2赞 Tenfour04 6/17/2022 #1

我无法解释为什么您在上面的代码中遇到任何问题,因为视图的点击侦听器只能在屏幕上调用时调用,这在逻辑上必须在被调用之前调用。但是,您还问是否有其他方法。就我个人而言,我发现我从一开始就不需要将绑定放在属性中,这将完全避免整个问题。onDestroyView()

您可以改为正常扩充视图,或者使用我在下面的示例中使用的构造函数快捷方式,该快捷方式允许您跳过重写函数。然后,可以使用 instead 而不是 将绑定附加到现有视图,然后在函数中独占使用它。当然,我从未使用过数据绑定,所以我只是假设有一个像视图绑定这样的函数。onCreateViewbind()inflate()onViewCreated()bind

class MyFragment: Fragment(R.layout.result_profile) {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val binding = ResultProfileBinding.bind(view)
            
        // Set up your UI here. Just avoid passing binding to callbacks that might
        // hold the reference until after the Fragment view is destroyed, such
        // as a network request callback, since that would leak the views.
        // But it would be fine if passing it to a coroutine launched using
        // viewLifecycleOwner.lifecycleScope.launch if it cooperates with
        // cancellation.
    }

}