android - 非法状态异常 : Activity has been destroyed (API level <21)

标签 android android-fragments kotlin android-4.4-kitkat fragmentmanager

我有一个带底栏的单一 Activity 应用程序。底部栏的每个选项卡都是一个 fragment ,充当容器并呈现多个子 fragment 。 仅在 Android 版本 <21 上应用程序崩溃并显示以下堆栈跟踪:

Process: de.name.dev, PID: 5262                                                                       
java.lang.IllegalStateException: Activity has been destroyed                                                                           
    at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1345)               
    at android.app.BackStackRecord.commitInternal(BackStackRecord.java:597)           
    at android.app.BackStackRecord.commit(BackStackRecord.java:575)        
    at de.xxxxxx.more.MoreFragment.onViewCreated(MoreFragment.kt:30)                
    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:904)               
    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)       
    at android.app.BackStackRecord.run(BackStackRecord.java:684)      
    at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1447)           
    at android.app.FragmentManagerImpl$1.run(FragmentManager.java:443)      
    at android.os.Handler.handleCallback(Handler.java:733)             
    at android.os.Handler.dispatchMessage(Handler.java:95)                         
    at android.os.Looper.loop(Looper.java:136)                         
    at android.app.ActivityThread.main(ActivityThread.java:5017)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
    at dalvik.system.NativeStart.main(Native Method)

我们的 ContainerFragment 看起来像这样:

class MoreFragment : KodeinFragment(), MoreOpenWebViewListener {

private val settingsFragment by lazy {
    SettingsFragment(this)
}

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

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View {
    return inflater.inflate(R.layout.fragment_more, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    childFragmentManager.beginTransaction()
        .add(R.id.more_container, settingsFragment)
        .commit()
}

...

onViewCreated 中,容器将要显示的 fragment 添加到其 childfragmentManager。 如果在选项卡之间导航, fragment 将被销毁并重新创建。 在您第二次访问 .commit() 时,它因上述堆栈跟踪而崩溃。

MoreFragment 在另一个 ContainerFragment 中实例化,即 TabBarFragment:

class TabBarFragment : KodeinFragment() {

private val sessionStore: SessionStore by instance()

private val fragment1 by lazy { Fragment1() }
private val moreFragment by lazy { MoreFragment() }

private val fragment2 by lazy { fragment2.newFragment2(sessionStore.data) }

var currentTabFragment: Fragment? = null
    private set

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    childFragmentManager
        .beginTransaction()
        .add(R.id.fragment_container, contractsFragment)
        .commit()
    bottomBar.selectTabAtPosition(0)
    bottomBar.setOnTabSelectListener { tabId ->
        when (tabId) {
            R.id.tab1 -> replaceFragment(fragment1)
            R.id.tab2 -> replaceFragment(fragment2)
            R.id.tab_settings -> replaceFragment(moreFragment)
        }
    }
    ViewCompat.setElevation(bottomBar, 8.0f * resources.displayMetrics.density)
}

private fun replaceFragment(fragment: Fragment) {
    childFragmentManager.beginTransaction().replace(R.id.fragment_container, fragment).commit()
    currentTabFragment = fragment
}
}

知道发生了什么吗?

最佳答案

在这里找到解决方案: Getting the error "Java.lang.IllegalStateException Activity has been destroyed" when using tabs with ViewPager这是 android 中的一个已知错误。

您必须覆盖使用 childFragmentManager 的 fragment 中的 onDetach() 并将其引用设置为 null。

override fun onDetach() {
    super.onDetach()

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        try {
            val childFragmentManager = Fragment::class.java!!.getDeclaredField("mChildFragmentManager")
            childFragmentManager.setAccessible(true)
            childFragmentManager.set(this, null)

        } catch (e: NoSuchFieldException) {
            throw RuntimeException(e)
        } catch (e: IllegalAccessException) {
            throw RuntimeException(e)
        }
    }
}

关于android - 非法状态异常 : Activity has been destroyed (API level <21),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45241248/

相关文章:

kotlin - 如何设置条件属性?

android - MPAndroidChart - 图例标签被切断

android - 分辨率感知图像不起作用 - Flutter

android - 为什么抽屉导航图标不显示在操作栏中?

android - 如何将变量从 AsyncTask 类返回到 fragment

amazon-web-services - AWS Amplify如何在身份验证期间检查密码是否正确?

c# - map 别针从未在我的 android 中绘制(xamarin 表单)

android - 如何在Android 10中获取IMEI

android - 无法从静态上下文引用非静态方法 getChildFragmentManager()

android - Kotlin中使用AlertDialog输入错误密码时如何返回输入界面?