Search code examples
androidkotlinfragment

java.lang.IllegalStateException: Fragment NotOlustur{1712dba} (eb74f985-d2c2-48d4-93de-d46a66d2e483) not attached to a context


I'm trying to write a program that sets a file in the Drawable over the ImageView in another fragment when the Button in the BottomSheet is clicked. But i think my context is always null. Because when i tried to add nullability (for example : context?.resources), it doesn't work but the app doesn't crash either. Here is my fragments:

Main Fragment

package com.ahmetkaan.kediy.Fragments

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.content.res.ResourcesCompat
import com.ahmetkaan.kediy.R
import com.ahmetkaan.kediy.databinding.FragmentNotOlusturBinding

class NotOlustur : Fragment() {

    private lateinit var binding : FragmentNotOlusturBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding.background.setOnClickListener {
            BottomSheet().show(parentFragmentManager, "newTaskTag")
        }
    }
    fun changeBackground0() {
        val background = view?.findViewById<ImageView>(R.id.background)
        val drawable = ResourcesCompat.getDrawable(requireContext().resources, R.drawable.retrofuture, null)
        background?.setImageDrawable(drawable)
    }
}

Bottom Sheet Fragment

package com.ahmetkaan.kediy.Fragments

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.ahmetkaan.kediy.databinding.FragmentBottomSheetBinding
import com.google.android.material.bottomsheet.BottomSheetDialogFragment

class BottomSheet : BottomSheetDialogFragment() {

    private lateinit var binding : FragmentBottomSheetBinding
    val NotOlustur = NotOlustur()

        override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)


        binding.imgPrew.setOnClickListener {
            NotOlustur.changeBackground0()
        }

        binding.imgPrew1.setOnClickListener {

        }

        binding.imgPrew2.setOnClickListener {

        }

        binding.imgPrew3.setOnClickListener {

        }
    }
}

Here is the Error Code

java.lang.IllegalStateException: Fragment NotOlustur{1712dba} (eb74f985-d2c2-48d4-93de-d46a66d2e483) not attached to a context.
    at androidx.fragment.app.Fragment.requireContext(Fragment.java:967)
    at com.ahmetkaan.kediy.Fragments.NotOlustur.changeBackground0(NotOlustur.kt:40)
    at com.ahmetkaan.kediy.Fragments.BottomSheet.onViewCreated$lambda-0(BottomSheet.kt:36)
    at com.ahmetkaan.kediy.Fragments.BottomSheet.$r8$lambda$mbZWmYt5DwS3MQ-Y8JU1Nc4q61M(Unknown Source:0)
    at com.ahmetkaan.kediy.Fragments.BottomSheet$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
    at android.view.View.performClick(View.java:7297)
    at android.view.View.performClickInternal(View.java:7274)
    at android.view.View.access$3600(View.java:819)
    at android.view.View$PerformClick.run(View.java:28017)
    at android.os.Handler.handleCallback(Handler.java:914)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:225)
    at android.app.ActivityThread.main(ActivityThread.java:7564)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

Solution

  • You're creating a brand new instance of your NotOlustur fragment by doing this:

    val NotOlustur = NotOlustur()
    

    So, yes, that brand new instance of NotOlustur was never added to a FragmentManager, just as the error message says.

    What you actually want is to get a reference to the fragment that created your BottomSheet Fragment. To do that, you need to make two changes:

    1. Use the correct FragmentManager when adding your BottomSheet:
    BottomSheet().show(childFragmentManager, "newTaskTag")
    

    This is what properly ties your NotOlustur and BottomSheet fragments together, rather than being completely independent Fragments in the same FragmentManager. With this change, BottomSheet will be a child fragment of NotOlustur.

    1. Retrieve the NotOlustur fragment by using requireParentFragment()
    // Note, variables should generally have a lowercase letter
    // so that they are not confused with a Class
    val notOlustur get() = requireParentFragment() as NotOlustur
    

    Instead of creating a brand new instance, we can use the correct nesting of the fragments to cast the result from requireParentFragment as your actual instance of NotOlustur. The get() here ensures that this line of code runs only when you actually access the variable, rather than instantly when the Fragment is created.