getViewBinding 中的 NullPointerException

NullPointerException in getViewBinding

提问人:mrbang 提问时间:8/24/2023 最后编辑:mrbang 更新时间:8/24/2023 访问量:47

问:

我有一个片段,它通过事件处理程序使用视图绑定。事件处理程序在 onResume() 和 onPause() 中设置和删除。在极少数情况下,通过事件访问视图会导致由于视图未初始化而导致崩溃(getViewBinding 中的 NullPointerException)。这些事件来自在前台服务中运行的后台作业,这就是 requireActivity().runOnUiThread{} 的原因。

我考虑做_viewBinding!可选并引入 nullPointerCheck。但这需要 nullpointer 检查许多不同的地方。另一种选择是引入带有 LiveData 对象的视图模型,但我想了解为什么这不起作用以及最佳修复建议。

这就是它的样子 - 剥离所有不相关的代码。我希望这会改变视图中按钮的状态,但会定期在行 viewBinding.manualConfigurationButton.visibility = View.VISIBLE 中获取 NullpointerException

@AndroidEntryPoint
class LaunchScreenFragment : Fragment(), IEnvConfigurationObserver {

  private var _viewBinding: FragmentLaunchscreenBinding? = null
  private val viewBinding get() = _viewBinding!

  override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?): View {
        _viewBinding = FragmentLaunchscreenBinding.inflate(inflater, container, false)
        return viewBinding.root
    }

  override fun onResume() {
     updateUI(false)
     envConfigurationRepository.addObserver(this)
     super.onResume()
  }

  override fun onPause() {
     envConfigurationRepository.removeObserver(this)
     super.onPause()
  }

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

  private fun updateState(isEnvironmentConfigurationInvalid: Boolean) {
    requireActivity().runOnUiThread {
      if (isEnvironmentConfigurationInvalid) {
        viewBinding.manualConfigurationButton.visibility = View.VISIBLE
      }else{
        viewBinding.manualConfigurationButton.visibility = View.GONE
      }
    }
  }

  override fun envConfUpdated(isValid: Boolean) {
    updateState(isValid)
  }
}

这是我们在应用程序崩溃时看到的例外:

java.lang.NullPointerException 位于 com.systematic.flow.general.launchscreen.ui.LaunchScreenFragment.getViewBinding(LaunchScreenFragment.kt:118) 在 com.systematic.flow.general.launchscreen.ui.LaunchScreenFragment.updateState$lambda$2(LaunchScreenFragment.kt:236) 在 com.systematic.flow.general.launchscreen.ui.LaunchScreenFragment.$r 8$lambda$7D38a3ZrFZSEHHlFdB43Rl-ao3A(未知 来源:0) 在 com.systematic.flow.general.launchscreen.ui.LaunchScreenFragment$$ExternalSyntheticLambda 3.run(未知 Source:2) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) 位于 android.os.Looper.loopOnce(Looper.java:226) 在 android.os.Looper.loop(Looper.java:313) 在 android.app.ActivityThread.main(ActivityThread.java:8757) 在 java.lang.reflect.Method.invoke(本机方法) com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)

android-fragments android-lifecycle observer-pattern android-viewbinding

评论

0赞 m0skit0 8/24/2023
这回答了你的问题吗?什么是 NullPointerException,如何修复它?
0赞 mrbang 8/24/2023
对不起,没有...这是关于 Android/Android 片段生命周期的特定问题,而不是关于如何处理 null / nullpointerexceptions 的一般问题。
0赞 David Wasser 8/30/2023
发生异常时是否暂停?Activity
0赞 mrbang 8/31/2023
经过一番调试,我找到了原因。与主线程同步可能需要很长时间(例如 500 毫秒)。这就是问题所在:Fragment 收到事件 -> 调用 runOnUiThread 并开始与主线程同步 -> 用户切换到其他 fragment -> fragment 被销毁 -> 调用 runOnUiThread 中的代码 -> viewBinding 为 null ->应用崩溃并出现 NullPointerException。我决定通过处理ViewModel中的事件来解决它,这样我就可以摆脱runOnUiThread。显然,我没有足够的分数来回答我自己的问题:(

答: 暂无答案