简体   繁体   中英

How to fix java.lang.IllegalStateException: Fragment not attached to a context

My application has a ViewPager with a bunch of fragments, when a button is clicked in Fragment1, actions are performed and a TransitionFragment appears, when a button is clicked in a TransitionFragment, the ViewPager transitions to Fragment3, this is how I implemented it: MainActivity.class

class MainActivity : AppCompatActivity() {

    private var mAdView: AdView? = null

    @SuppressLint("ResourceType")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val adRequest = AdRequest.Builder().build()
        mAdView = findViewById(R.id.adView)
        mAdView!!.loadAd(adRequest)

        initTab()

    }

    fun initTab() {
        tab_layout.addTab(tab_layout.newTab().setIcon(R.drawable.image1)
        tab_layout.addTab(tab_layout.newTab().setIcon(R.drawable.image2)
        tab_layout.addTab(tab_layout.newTab().setIcon(R.drawable.image3)

        tab_layout.tabGravity = TabLayout.GRAVITY_FILL

        val adapter = MyPagerAdapter(supportFragmentManager, tab_layout.tabCount)
        pager.adapter = adapter

        pager.offscreenPageLimit = 2

        pager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tab_layout))

        tab_layout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
            override fun onTabSelected(tab: TabLayout.Tab) {
                pager.currentItem = tab.position
                if (tab.position == 0) {
                    tab_layout.getTabAt(0)!!.setIcon(R.drawable.image1_focus)
            if (getSupportFragmentManager().findFragmentById(R.id.frame) != null) {
                            getSupportFragmentManager().popBackStack();
                        }
                }
                if (tab.position == 1) {
                    tab_layout.getTabAt(1)!!.setIcon(R.drawable.image2_focus)
            if (getSupportFragmentManager().findFragmentById(R.id.frame) != null) {
                            getSupportFragmentManager().popBackStack();
                        }
                }
                if (tab.position == 2) {
                    tab_layout.getTabAt(2)!!.setIcon(R.drawable.image3_focus)
            if (getSupportFragmentManager().findFragmentById(R.id.frame) != null) {
                            getSupportFragmentManager().popBackStack();
                     }
                }
            }

            override fun onTabUnselected(tab: TabLayout.Tab) {
                if (tab.position == 0) tab_layout.getTabAt(0)!!.setIcon(R.drawable.image1)
                if (tab.position == 1) tab_layout.getTabAt(1)!!.setIcon(R.drawable.image2)
                if (tab.position == 2) tab_layout.getTabAt(2)!!.setIcon(R.drawable.image3)
            }

            override fun onTabReselected(tab: TabLayout.Tab) {

            }
        })
    }

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:fitsSystemWindows="true"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/frame"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@id/tab_layout"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <com.google.android.gms.ads.AdView
                android:id="@+id/adView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:background="@color/transparent"
                app:adSize="SMART_BANNER"
                app:adUnitId="@string/banner_key"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                style="@style/MyToolbar"
                android:layout_width="match_parent"
                android:layout_height="35dp"
                android:layout_marginTop="2dp"
                android:gravity="center"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/adView"
                app:popupTheme="@style/AppTheme.PopupOverlay">

                <TextView
                    android:id="@+id/toolbar_txt"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:fontFamily="@font/sf_pro_display_regular"
                    android:textColor="@color/black"
                    android:textSize="24sp"
                    tools:layout_editor_absoluteX="206dp"
                    tools:layout_editor_absoluteY="7dp" />

            </androidx.appcompat.widget.Toolbar>

            <androidx.viewpager.widget.ViewPager
                android:id="@+id/pager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_constraintBottom_toTopOf="@+id/tab_layout"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/toolbar" />

        </LinearLayout>
    </FrameLayout>

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="#fff"
        android:elevation="6dp"
        android:minHeight="?attr/actionBarSize"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:tabBackground="@drawable/tab_color_selector"
        app:tabIndicatorColor="#2196F3"
        app:tabIndicatorGravity="top"
        app:tabIndicatorHeight="4dp" />

</androidx.constraintlayout.widget.ConstraintLayout>

Fragment1.class

class Fragment1 : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment1, container, false)

        return view
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
 
            optbutton.setOnClickListener {
        
        val transitionFragment: TransitionFragment = TransitionFragment().newInstance(2)!!
            val trans = fragmentManager!!.beginTransaction()
            trans.replace(R.id.frame, transitionFragment)
        trans.addToBackStack(null)
            trans.commit()
        }

    }
}

Fragment1 and TransitionFragment only have a button TransitionFragment.class

class TransitionFragment() : Fragment() {

    private var index: Int = 0

    fun newInstance(index: Int): TransitionFragment? {
        val fragment = TransitionFragment()
        val args = Bundle()
        args.putInt("index", index)
        fragment.setArguments(args)
        return fragment
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.transition_fragment, container, false)
        val trans_btn: Button = view.findViewById(R.id.trans_btn)

        if (getArguments() != null) {
            index = getArguments()!!.getInt("index")
        }

        return view
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        trans_btn.setOnClickListener {
            val tabs: TabLayout = activity!!.findViewById(R.id.tab_layout)
            tabs.getTabAt(index)!!.select()

        }
    }

}

Everything works well, but in rare cases the metric receives a crash notification like this:

java.lang.IllegalStateException: Fragment e{2dc5257 (30032337-24f8-4d9a-9da9-9db92da88082)} not attached to a context.
    at androidx.fragment.app.d.q(Unknown Source)
    at androidx.fragment.app.d.u(Unknown Source)
    at androidx.fragment.app.d.a(Unknown Source)
    at {packageWithFragment}.e.aE(Unknown Source)
    at {packageWithFragment}.e.c(Unknown Source)
    at {packageWithFragment}.e$f.b(Unknown Source)
    at com.hookedonplay.decoviewlib.b.a.n(Unknown Source)
    at com.hookedonplay.decoviewlib.a.b$2.a(Unknown Source)
    at com.a.a.j.n(Unknown Source)
    at com.a.a.j.c(Unknown Source)
    at com.a.a.j$a.handleMessage(Unknown Source)
    at android.os.Handler.dispatchMessage(Handler.java:111)
    at android.os.Looper.loop(Looper.java:227)
    at android.app.ActivityThread.main(ActivityThread.java:6102)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:961)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:822)

I can't figure out where the error is and what is causing the crash. Please tell me what could be wrong and how to fix it correctly?!

I had kind of similiar case: when I went back from a fragment, I got crashed and had the same error as yours.

I did a simple check and put Log.i ("info", x) after every few lines in the fragment code and also overrdie onStop and put Log inside it (increasing the x each time). Surprisingly I found out that the fragment code keeps running after onStop , and got crashed whan it comes to get a view like a Textview etc, because the Fragment Context is NULL now... (In my case it was because I have a calling to firebase database, pulling data and then write it to a view. It takes a while, and if I leave the fragment before this proccess ends, the view in null).

I've searched a lot but couldn't find any information or other questions about it... weird.

My soulotion: I made a boolean flag, initialize it with true at onCreateView and assign false to it at onStop . Now, before I call any view at the code, I validate the flag isn't false. That solved my crashes.

I still will be glad to understand that life-cycle and why Fragment code keeps runing after onStop ... I hope I helped you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM