Search code examples
androidnullpointerexceptionfragmentandroid-lifecycleandroid-savedstate

Fragment onSaveInstanceState() called after onDestroyView()


The application started to receive some crashes (it is not reproducible 100%) due to some lifecycle issue for the Fragment.

I'm using view binding and I'm manually invalidating the binding as per Android recommendations to avoid high memory usage in case the reference to the binding is kept after the Fragment is destroyed.

private var _binding: FragmentCustomBinding? = null
private val binding get() = _binding!!

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View = FragmentCustomBinding.inflate(inflater, container, false).also {
    _binding = it
}.root

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

override fun onSaveInstanceState(outState: Bundle) {
    outState.apply {
        putString(BUNDLE_KEY_SOME_VALUE, binding.etSomeValue.text.toString())
    }
    super.onSaveInstanceState(outState)
}

I'm getting a NullPointerException in onSaveInstanceState() as the binding is null as this was called after onDestroyView().

Any idea how I could solve this without manually creating a saved state and manually handling it?


Solution

  • It seems the answer for this is in how the fragments are handled, even when they do not have a view, as changes in the Activity state can still trigger onSavedInstanceState() thus I can end up in scenarios where I am in onSavedInstanceState() but without a view. This seems to be intentional as fragments are still supported whether they have a view or not.

    The recommendation was to use the view APIs for saving and restoring state (or my SavedStateRegistery).

    A few more details can be found here: https://issuetracker.google.com/issues/245355409