• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Why would an error say "Fragment not attached to Activity" when onDetach has never been called?

Mimsy

Lurker
Jun 23, 2023
4
1
I am pretty new to Android Dev, although not new to programming in general. I'm comfortable with the basics of Android but have moved on to data persistence and am having trouble - I'm used to raw SQL queries and APIs, and am finding the Android model a little obscure. I have implemented a Room database. It has a DataViewModel that takes a DataRepository in its constructor, and therefore uses a ViewModelProvider.Factory to be instantiated.

In my opening Fragment, I want to get some basic data from users that is stored locally on the Room database - all String values (first and last name etc.). The UI gets up and running and the Fragment successfully attaches to the Activity (I am using a single Activity with multiple Fragments).

When the function to submit the user input to the database is called, the app crashes and I get the error "Fragment WelcomeFragment... not attached to an Activity" even though according to my Logcat, the onDetach() function never gets called. This makes me think the error is a red herring and something else is going on, but I have been fiddling for 5 days and haven't been able to solve it. The application called PawsApplication is in my Manifest file.

These are the relevant parts in my Fragment. It crashes right after the "Insert Client" - "Start" tag, so on the insertClient() call to the ViewModel:

Code:
    private val dataViewModel : DataViewModel by activityViewModels {
        DataViewModelFactory()
    }

Code:
fun submitToDb(f_name: String, l_name: String, a_name: String, role: String){
        val newClient = Client(0, f_name, l_name, role, a_name)
        Log.d("Insert Client", "Start")
        dataViewModel.insertClient(newClient)
        Log.d("Insert Client", "Finished")

    }
    override fun onDetach() {
        super.onDetach()
        Log.d("WelcomeFragment", "On detach")
    }

And my ViewModel factory code:

Code:
class DataViewModelFactory(): ViewModelProvider.Factory {
    override fun <T: ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {
        val application = checkNotNull(extras[APPLICATION_KEY])
        if(modelClass.isAssignableFrom(DataViewModel::class.java)){
            @Suppress("UNCHECKED_CAST")
            return DataViewModel(
                (application as PawsApplication).repository
            ) as T

        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

I am feeling a bit clueless at the moment! Is this a problem anyone else has run into? I've been trawling Stack Overflow for days, but haven't found a relevant solution yet. If more code is required, please ask.

Edit: forgot to add the Logcat - sorry!
Code:
FATAL EXCEPTION: main
                                                                                                    Process: com.miriam.helpingpaws, PID: 2622
                                                                                                    java.lang.IllegalStateException: Fragment WelcomeFragment{276ac35} (3be3fa8f-b72d-45e4-b0b3-4ae1274d8df2) not attached to an activity.
                                                                                                        at androidx.fragment.app.Fragment.requireActivity(Fragment.java:1000)
                                                                                                        at com.miriam.helpingpaws.welcome.WelcomeFragment.submitToDb(WelcomeFragment.kt:70)
                                                                                                        at com.miriam.helpingpaws.welcome.WelcomeScreenKt$WelcomeScreen$1$5.invoke(WelcomeScreen.kt:86)
                                                                                                        at com.miriam.helpingpaws.welcome.WelcomeScreenKt$WelcomeScreen$1$5.invoke(WelcomeScreen.kt:86)
                                                                                                        at androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$1$2.invoke-k-4lQ0M(Clickable.kt:167)
                                                                                                        at androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$1$2.invoke(Clickable.kt:156)
                                                                                                        at androidx.compose.foundation.gestures.TapGestureDetectorKt$detectTapAndPress$2$1$1.invokeSuspend(TapGestureDetector.kt:234)
                                                                                                        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                        at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:178)
                                                                                                        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
                                                                                                        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
                                                                                                        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:431)
                                                                                                        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:420)
                                                                                                        at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:328)
                                                                                                        at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter$PointerEventHandlerCoroutine.offerPointerEvent(SuspendingPointerInputFilter.kt:566)
                                                                                                        at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter.dispatchPointerEvent(SuspendingPointerInputFilter.kt:456)
                                                                                                        at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter.onPointerEvent-H0pRuoY(SuspendingPointerInputFilter.kt:469)
                                                                                                        at androidx.compose.ui.node.BackwardsCompatNode.onPointerEvent-H0pRuoY(BackwardsCompatNode.kt:394)
                                                                                                        at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:314)
                                                                                                        at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:301)
                                                                                                        at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass(HitPathTracker.kt:183)
                                                                                                        at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges(HitPathTracker.kt:102)
                                                                                                        at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-BIzXfog(PointerInputEventProcessor.kt:98)
                                                                                                        at androidx.compose.ui.platform.AndroidComposeView.sendMotionEvent-8iAsVTc(AndroidComposeView.android.kt:1329)
                                                                                                        at androidx.compose.ui.platform.AndroidComposeView.handleMotionEvent-8iAsVTc(AndroidComposeView.android.kt:1275)
                                                                                                        at androidx.compose.ui.platform.AndroidComposeView.dispatchTouchEvent(AndroidComposeView.android.kt:1214)
                                                                                                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
                                                                                                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
                                                                                                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
                                                                                                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
                                                                                                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
                                                                                                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
                                                                                                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
                                                                                                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
                                                                                                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
                                                                                                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
                                                                                                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
                                                                                                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
                                                                                                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
                                                                                                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
                                                                                                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
                                                                                                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
2023-06-23 14:13:54.849  2622-2622  AndroidRuntime          com.miriam.helpingpaws               E      at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
                                                                                                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
                                                                                                        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
                                                                                                        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
                                                                                                        at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:502)
                                                                                                        at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1890)
                                                                                                        at android.app.Activity.dispatchTouchEvent(Activity.java:4199)
                                                                                                        at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:70)
                                                                                                        at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:460)
                                                                                                        at android.view.View.dispatchPointerEvent(View.java:14858)
                                                                                                        at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6446)
                                                                                                        at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6247)
                                                                                                        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5725)
                                                                                                        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5782)
                                                                                                        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5748)
                                                                                                        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5913)
                                                                                                        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5756)
                                                                                                        at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5970)
                                                                                                        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5729)
                                                                                                        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5782)
                                                                                                        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5748)
                                                                                                        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5756)
                                                                                                        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5729)
                                                                                                        at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8696)
                                                                                                        at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8647)
                                                                                                        at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:8616)
                                                                                                        at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8819)
                                                                                                        at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:259)
                                                                                                        at android.os.MessageQueue.nativePollOnce(Native Method)
                                                                                                        at android.os.MessageQueue.next(MessageQueue.java:335)
                                                                                                        at android.os.Looper.loopOnce(Looper.java:161)
                                                                                                        at android.os.Looper.loop(Looper.java:288)
                                                                                                        at android.app.ActivityThread.main(ActivityThread.java:7842)
                                                                                                        at java.lang.reflect.Method.invoke(Native Method)
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
                                                                                                        Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@8b58796, androidx.compose.runtime.BroadcastFrameClock@89e9f17, StandaloneCoroutine{Cancelling}@2ccef04, AndroidUiDispatcher@32d2ced]
 
FINALLY figured it out. I was creating new WelcomeFragments on every call, which of course were not attached to the Activity - only the original WelcomeFragment was. I passed "this@WelcomeFragment" to my Compose UI so that I could call it without creating a new one. All works now.

Thanks! It actually helps to just type out the problem :)
 
Upvote 0

BEST TECH IN 2023

We've been tracking upcoming products and ranking the best tech since 2007. Thanks for trusting our opinion: we get rewarded through affiliate links that earn us a commission and we invite you to learn more about us.

Smartphones