Fragment not associated with a fragment manager after screen rotation in Android

455 Views Asked by At

I have a problem I can't solve. I have two fragments, one called "NotificationListFragment" that can navigate to a second fragment called "InfoNotificationFragment". Before calling the second fragment, I pass two parameters through the Bundle object:

  • A closure of type "() -> Unit" that needs to be executed when the second fragment is closed;
  • An object of type "MessageNotificationCompatible". Both are passed as Parcelable objects. The closure is set inside a class called "TrackedReference", which contains a map of objects of type "WeakReference", in order to avoid implementing marshalling.

Let me show you how this is done in the "NotificationListFragment" class:

adapter.action.observe(viewLifecycleOwner) { action ->
            when(action) {
                is NotificationAction.SelectionAction -> {
                    val message = action.infoNotification.toNotificationMessage()

                    val handler: () -> Unit = {
                        markInfoNotificationAsReadInRV(message.data.getID())
                        findNavController().navigateUp()
                    }

                    val closeHandler : CloseHandlerCompatible = CloseHandler(handler)

                    val b = Bundle()
                    b.putParcelable(InfoNotificationFragment.MESSAGE_KEY, message)
                    b.putParcelable(InfoNotificationFragment.CLOSURE_KEY, TrackedReference(closeHandler))

                    findNavController().navigate(R.id.action_notificationListFragment_to_infoNotificationFragment, b)
                }
            }
        }

Inside the "InfoNotificationFragment" class, within the "onCreate()" method, the parameters passed through the Bundle are retrieved:

arguments?.let { bundle->
            val closure : TrackedReference<*>

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                message = bundle.getParcelable(MESSAGE_KEY, NotificationMessageCompatible::class.java)
                closure = bundle.getParcelable(CLOSURE_KEY, TrackedReference::class.java) as TrackedReference<*>
            } else {
                @Suppress("DEPRECATION")
                message = bundle.getParcelable(MESSAGE_KEY)
                @Suppress("DEPRECATION")
                closure = (bundle.getParcelable(CLOSURE_KEY) as? TrackedReference<*>)!!
            }

            closeHandler = (closure.get as CloseHandlerCompatible).closeHandler
            closure.removeStrongReference()
        }

This second fragment has a button that, when clicked, calls the closure that was passed to it as a parameter:

binding.closeButton.setOnClickListener {

            // Need for smart cast
            val message = message ?: return@setOnClickListener

            // I mark the notification it as read in memory
            viewModel.markInfoNotificationAsRead(message.data.getID())

            // I call the closeHandler method
            this.closeHandler()
        }

The problem I'm encountering is the following: everything works correctly following the standard flow. However, when the app remains in the background for a long time, and the activity and fragment view are recreated, I can no longer call the "findNavController().navigateUp()" method inside the closure.

Since the problem occurs at an unspecified time, I tried to simulate the same situation by attempting to activate the screen orientation (which is disabled by default for this activity).

Actually, by rotating the screen, I find myself in the same situation as when the app is in the background, so I can simulate this problem. In any case, the exception that I get when I try to call the "findNavController().navigateUp()" method after rotating the screen is the following:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: it.zucchetti.fq.qid, PID: 29563
    java.lang.IllegalStateException: Fragment NotificationListFragment{846f563} (fc633911-2609-4220-8236-acfda3b0a01b) not associated with a fragment manager.
        at androidx.fragment.app.Fragment.getParentFragmentManager(Fragment.java:1107)
        at androidx.navigation.fragment.NavHostFragment$Companion.findNavController(NavHostFragment.kt:375)
        at androidx.navigation.fragment.FragmentKt.findNavController(Fragment.kt:29)
        at it.zucchetti.qauthenticator.ui.notificationlist.NotificationListFragment$onSuccess$1$handler$1.invoke(NotificationListFragment.kt:158)
        at it.zucchetti.qauthenticator.ui.notificationlist.NotificationListFragment$onSuccess$1$handler$1.invoke(NotificationListFragment.kt:155)
        at it.zucchetti.qauthenticator.ui.notification.info.InfoNotificationFragment.bindData$lambda$1(InfoNotificationFragment.kt:110)
        at it.zucchetti.qauthenticator.ui.notification.info.InfoNotificationFragment.$r8$lambda$Trhe-1LjjI1Cfn283v0VQLwE1u0(Unknown Source:0)
        at it.zucchetti.qauthenticator.ui.notification.info.InfoNotificationFragment$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
        at android.view.View.performClick(View.java:7792)
        at android.widget.TextView.performClick(TextView.java:16112)
        at android.view.View.performClickInternal(View.java:7769)
        at android.view.View.access$3800(View.java:910)
        at android.view.View$PerformClick.run(View.java:30218)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:226)
        at android.os.Looper.loop(Looper.java:313)
        at android.app.ActivityThread.main(ActivityThread.java:8663)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)

Could you tell me how to solve the problem?

I tried to change the way to go back to the previous fragment, to save the fragment's state, to save the NavHostFragment's state, but I still haven't solved the problem.

0

There are 0 best solutions below