IllegalStateException:Activity 已被销毁(API 级别 <21)
IllegalStateException: Activity has been destroyed (API level <21)
我有一个带有底部栏的单一 Activity 应用程序。底部栏的每个选项卡都是一个片段,充当容器并呈现多个子片段。
仅在 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.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
中,容器将要显示的片段添加到其 childfragmentManager
。
如果在选项卡之间导航,片段将被销毁并重新创建。
在您第二次进入 .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
的片段中的 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)
}
}
}
我有一个带有底部栏的单一 Activity 应用程序。底部栏的每个选项卡都是一个片段,充当容器并呈现多个子片段。 仅在 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.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
中,容器将要显示的片段添加到其 childfragmentManager
。
如果在选项卡之间导航,片段将被销毁并重新创建。
在您第二次进入 .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
的片段中的 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)
}
}
}