【问题标题】:Fragments inside other fragment: crash with "has not been attached yet."其他片段中的片段:“尚未附加”崩溃。
【发布时间】:2020-02-07 16:50:54
【问题描述】:

您好,我有一个奇怪的问题。 MainActivity 有一个框架布局和一个主片段 EnterFragment。 EnterFragment 有一个框架布局,我想看看其他 2 个片段。 SignupFragment 和LoginFragment。 EnterFragment 启动时显示SignupFragment.java.. 在MainActivity 调用EnterFragment 的方法将fragment 更改为LoginFragment 但应用程序崩溃后:

java.lang.IllegalStateException: Fragment EnterFragment{95bc7de (70f980b2-eff8-4e4c-a644-e95544b73584)} has not been attached yet.
    at androidx.fragment.app.Fragment.getChildFragmentManager(Fragment.java:923)

这里是项目:https://www.dropbox.com/s/qq1kl4qw688ipjr/example.zip?dl=0

代码如下:

//MainActivity
class MainActivity : AppCompatActivity() {
    private var enterFragment: EnterFragment?=null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        showEnter()
    }
    private fun showEnter() {
            enterFragment=  EnterFragment.newInstance()
            this.replaceFragmentTransition(R.id.fragmentContainer, EnterFragment.newInstance(), EnterFragment.TAG )
            var handler= Handler()
            handler.postDelayed(Runnable {gotoLoginFromSignup() }, 8000)
        }
    private fun gotoLoginFromSignup() {
        enterFragment?.gotoLogin()
    }
}

//EnterFragment
    class EnterFragment : Fragment() {

        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            return inflater.inflate(R.layout.fragment_enrer, container, false)
        }
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            super.onActivityCreated(savedInstanceState)
            this.replaceFragmentTransition(R.id.fmContainer, SignuFragment.newInstance(), SignuFragment.TAG )
        }
        fun gotoLogin(){
            this.replaceFragmentTransition(R.id.fmContainer, LoginFragment.newInstance(), SignuFragment.TAG )
        }

        companion object {
            val TAG: String="EnterFragment"
            @JvmStatic
            fun newInstance() = EnterFragment()
        }
    }
    //SignupFragment
    class SignuFragment : Fragment() {
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            return inflater.inflate(R.layout.fragment_signup, container, false)
        }
        companion object {
            val TAG: String="SignuFragment"
            @JvmStatic
            fun newInstance() = SignuFragment()
        }
    }
    //LoginFragment
    class LoginFragment : Fragment() {
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            return inflater.inflate(R.layout.fragment_login, container, false)
        }
        companion object {
            val TAG: String="LoginFragment"
            @JvmStatic
            fun newInstance() = LoginFragment()
        }
    }
    //EXTENSIONS
    fun FragmentActivity.replaceFragmentTransition(
        container: Int,
        fragment: Fragment?,
        tag: String
    ) {
        fragment?.let {
            var transition = this.supportFragmentManager
                .beginTransaction()
            transition.replace(container, it, tag)
                .commitNowAllowingStateLoss()
        }
    }
    fun Fragment.replaceFragmentTransition(
        container: Int,
        fragment: Fragment?,
        tag: String
    ) {
        fragment?.let {
                var transition = this.childFragmentManager
                    .beginTransaction()
                transition.replace(container, it, tag)
                    .commitNowAllowingStateLoss()
            }
    }
    //main activity layout
    <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:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/fragmentContainer"
            android:layout_width="0dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            android:layout_height="0dp" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    //enterFragment
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        tools:context=".EnterFragment">
        <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/fmContainer"
            android:layout_width="0dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            android:layout_height="0dp" />
    </androidx.constraintlayout.widget.ConstraintLayout>

【问题讨论】:

  • 如果我误解了您的问题,请更正。所以基本上在应用程序启动时,首先你要显示注册片段,然后在 8 秒后显示登录片段
  • 8 秒延迟是一个测试。在我的应用程序中,注册内的一个按钮使用 Activity 来显示登录。
  • 好的,注册片段中有一个按钮,点击它,你要打开登录片段
  • 是的。 Activity->EnterFragment->SignupFragment (button...(activity.showLogin())->Activity->enterFragment.showLogin()...
  • 好吧,我改变了我的例子。这里代码:dropbox.com/s/qq1kl4qw688ipjr/example.zip?dl=0

标签: android android-fragments


【解决方案1】:

替换这个

this.replaceFragment(R.id.fragmentContainer, FatherFragment.newInstance(), FatherFragment.TAG )

  this.replaceFragment(R.id.fragmentContainer, fatherFragment!!, FatherFragment.TAG )

在交易时,您正在传递不同的实例并使用另一个实例调用 openLogin()。

FatherFragment.newInstance() will give new instance.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-27
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    相关资源
    最近更新 更多