I am getting a does not have a NavController set
error inside a OnBackPressedCallback. Here is the code
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
fragmentView = inflater.inflate(R.layout.patient_info_fragment, container, false)
if(Utils.connectedToInternet()){
fragmentView.pastScreeningsButton.visibility = View.GONE
}
requireActivity().onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
Navigation.findNavController(fragmentView).navigate(R.id.action_patientInfoFragment_to_patientsList)
}
})
setHasOptionsMenu(true)
return fragmentView
}
I am only getting this error when I come back into the fragment where this is implemented.
I have android:name="androidx.navigation.fragment.NavHostFragment"
in the home fragment.
To clarify, I am using Navigation controller to do all my Navigation around my app and it works just fine. I only get this error inside this OnBackPressedCallback
and only when the user navigates back into the fragment where this is implemented.
Let me know if you need to see any more of my code.
You might run into an issue with leaks of old instances of your fragment. Also it's not a good practice to store the created view within another variable like fragmentView
. All in all your onCreateView
implementation is doing too many things unrelated to its purpose.
I'd suggest to split up the functionality into relevant life-cycle methods and use the fragment.view
directly within your callback. To not run into an issue with unattached views, you then bind and unbind the callback with the life-cycle.
class PatientInfoFragment: Fragment() {
private val callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
Navigation.findNavController(view).navigate(R.id.action_patientInfoFragment_to_patientsList)
}
}
override fun onCreate(
savedInstanceState: Bundle?
) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = inflater.inflate(R.layout.patient_info_fragment, container, false)
override fun onViewCreated(
view: View,
savedInstanceState: Bundle?
) {
if(Utils.connectedToInternet()){
view.pastScreeningsButton.visibility = View.GONE
}
}
override fun onStart() {
super.onStart()
requireActivity().onBackPressedDispatcher.addCallback(callback)
}
override fun onStop() {
callback.remove()
super.onStop()
}
}
The callback life-cycle binding can be bound with the fragment as lifecycle owner calling the other addCallback(LifecycleOwner, OnBackPressedCallback)
.
Additionally you could have a look into Android KTX and Kotlin Android Extensions to simplify your implementation.