如何防止FragmentManager在旋转后被销毁
How to prevent FragmentManager from being destroyed after rotation
当我单击“显示更多”按钮时,会打开一个新片段。但是,如果我旋转设备然后单击它,则会出现错误。
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.rekijan.initiativetrackersecondedition, PID: 4673
java.lang.IllegalStateException: FragmentManager has been destroyed
at androidx.fragment.app.FragmentManager.enqueueAction(FragmentManager.java:1878)
at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:329)
at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:294)
at com.rekijan.initiativetrackersecondedition.ui.activities.MainActivity.replaceCharacterDetailFragment(MainActivity.java:207)
at com.rekijan.initiativetrackersecondedition.character.adapter.CharacterAdapter.onClick(CharacterAdapter.java:305)
at android.view.View.performClick(View.java:7448)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access00(View.java:810)
at android.view.View$PerformClick.run(View.java:28305)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
所以代码在 RecyclerViewAdapter 中
holder.showCharacterDetailButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
((MainActivity)context).replaceCharacterDetailFragment(holder.getAdapterPosition());
}
});
然后在MainActivity
public void replaceCharacterDetailFragment(int position) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (getResources().getBoolean(R.bool.isTablet)) {
transaction.replace(R.id.second_fragment_container, CharacterDetailFragment.newInstance(position));
transaction.commit();
} else {
transaction.replace(R.id.main_fragment_container, CharacterDetailFragment.newInstance(position));
transaction.addToBackStack(null);
transaction.commit();
//Enable the back button in action bar
if (getSupportActionBar() != null) getSupportActionBar().setDisplayHomeAsUpEnabled(true);
AppExtension app = (AppExtension) this.getApplicationContext();
app.setShowBackNavigation(true);
}
}
更多代码可以在 github 中找到,因为开源是 https://github.com/ej-krielen/pf2initiativetracker
一个常见的 'solution' 是使用 isDestroyed 或 isFinishing。当然,如果我使用它,应用程序不会崩溃,但也不会制作片段。
所以重申一下:
- 片段一开始没问题,但旋转后就不行了。
- FragmentManager 被销毁了?如何获得back/properly使用它?
是的,有时在更新旧项目时您会忘记自己的逻辑。问题是在我的适配器中我使用了对上下文的引用。但是,适配器是在 AppExtension 中创建的,因此在重新创建 Activity 时不会再次设置。所以现在当 Activity 重新创建时,我再次将上下文传递给适配器,一切正常。
当我单击“显示更多”按钮时,会打开一个新片段。但是,如果我旋转设备然后单击它,则会出现错误。
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.rekijan.initiativetrackersecondedition, PID: 4673
java.lang.IllegalStateException: FragmentManager has been destroyed
at androidx.fragment.app.FragmentManager.enqueueAction(FragmentManager.java:1878)
at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:329)
at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:294)
at com.rekijan.initiativetrackersecondedition.ui.activities.MainActivity.replaceCharacterDetailFragment(MainActivity.java:207)
at com.rekijan.initiativetrackersecondedition.character.adapter.CharacterAdapter.onClick(CharacterAdapter.java:305)
at android.view.View.performClick(View.java:7448)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access00(View.java:810)
at android.view.View$PerformClick.run(View.java:28305)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
所以代码在 RecyclerViewAdapter 中
holder.showCharacterDetailButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
((MainActivity)context).replaceCharacterDetailFragment(holder.getAdapterPosition());
}
});
然后在MainActivity
public void replaceCharacterDetailFragment(int position) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (getResources().getBoolean(R.bool.isTablet)) {
transaction.replace(R.id.second_fragment_container, CharacterDetailFragment.newInstance(position));
transaction.commit();
} else {
transaction.replace(R.id.main_fragment_container, CharacterDetailFragment.newInstance(position));
transaction.addToBackStack(null);
transaction.commit();
//Enable the back button in action bar
if (getSupportActionBar() != null) getSupportActionBar().setDisplayHomeAsUpEnabled(true);
AppExtension app = (AppExtension) this.getApplicationContext();
app.setShowBackNavigation(true);
}
}
更多代码可以在 github 中找到,因为开源是 https://github.com/ej-krielen/pf2initiativetracker
一个常见的 'solution' 是使用 isDestroyed 或 isFinishing。当然,如果我使用它,应用程序不会崩溃,但也不会制作片段。
所以重申一下:
- 片段一开始没问题,但旋转后就不行了。
- FragmentManager 被销毁了?如何获得back/properly使用它?
是的,有时在更新旧项目时您会忘记自己的逻辑。问题是在我的适配器中我使用了对上下文的引用。但是,适配器是在 AppExtension 中创建的,因此在重新创建 Activity 时不会再次设置。所以现在当 Activity 重新创建时,我再次将上下文传递给适配器,一切正常。