【问题标题】:How to fix java.lang.IllegalStateException: Fragment not attached to a context如何修复 java.lang.IllegalStateException:片段未附加到上下文
【发布时间】:2023-04-04 08:50:01
【问题描述】:

我的应用程序有一个带有一堆片段的ViewPager,当在Fragment1中单击一个按钮时,会执行操作并出现一个TransitionFragment,当在TransitionFragment中单击一个按钮时,ViewPager会过渡到Fragment3,这就是我的实现方式它: 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 和 TransitionFragment 只有一个按钮 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()

        }
    }

}

一切正常,但在极少数情况下,指标会收到如下崩溃通知:

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)

我无法弄清楚错误在哪里以及导致崩溃的原因。请告诉我可能出了什么问题以及如何正确解决?!

【问题讨论】:

    标签: android kotlin android-fragments android-viewpager fragmenttransaction


    【解决方案1】:

    我有一种类似的情况:当我从一个片段返回时,我崩溃了,并且遇到了和你一样的错误。

    我做了一个简单的检查,并在fragment 代码中每隔几行加上Log.i ("info", x) 并覆盖onStop 并将Log 放入其中(每次增加x)。令人惊讶的是,我发现片段代码在onStop 之后一直运行,并且在获得view 时崩溃了,比如Textview 等,因为Fragment Context 现在为NULL。 ..(在我的情况下,这是因为我调用了firebase数据库,提取数据然后将其写入视图。这需要一段时间,如果我在此过程结束之前离开片段,则视图为空)。

    我搜索了很多,但找不到任何信息或其他有关它的问题……很奇怪。

    我的灵魂:我创建了一个布尔标志,在onCreateView 使用true 对其进行初始化,并在onStopfalse 分配给它。现在,在我调用代码中的任何视图之前,我验证标志不是假的。这解决了我的崩溃问题。

    我仍然会很高兴了解这个生命周期以及为什么 Fragment 代码在 onStop 之后一直运行...希望对您有所帮助。

    【讨论】:

    • 这是 Android 中的标准且令人头疼的问题。详细查看Fragment lifecycle 了解一下。要么,它会继续产生问题(这是一个非常糟糕的模式实现),但至少你将能够管理。
    • Tnx @Sourcerer,我以前读过,但对这种讨厌的行为不是很清楚......而且他们不会让你有任何灵魂来处理这种情况......什么你会处理它吗?
    • 我知道这真的很烦人。在一年的时间里,我用 A3 打印了两个(活动和片段)生命周期并在我面前。没有(或我无法找到)简单的解决方案。只为追踪每一个事件并检测情况。我的案例是中等复杂的(一些后台进程、一些拉取通知、一些外部活动)并且需要很长时间才能更正(Google Play 仍然报告了一些崩溃)。
    • Tnx...生活很复杂
    猜你喜欢
    • 1970-01-01
    • 2015-04-24
    • 2021-09-28
    • 2018-09-20
    • 2020-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多