Mat*_*hew 26 android android-fragments
Android平台:3.1
我试图将一个片段从容器A移动到容器B.下面是完成此操作的代码:
private void reattach(int newContainerId, Fragment frag, String tag) {
if (frag == null || !frag.isAdded() || (frag.getId() == newContainerId)) { return; }
final FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.remove(frag); //stacco il frammento dal container A
ft.commit();
fm.executePendingTransactions();
ft = fm.beginTransaction();
ft.add(newContainerId, frag, tag); //attacco il frammento sul container D
ft.commit();
fm.executePendingTransactions();
}
Run Code Online (Sandbox Code Playgroud)
当我运行系统时,我得到以下IllegalStateException:
03-26 00:13:14.829: E/AndroidRuntime(30090): java.lang.RuntimeException: Unable to start activity ComponentInfo{eu.areamobile.apps.sfa/eu.areamobile.apps.sfa.activity.HomeActivity}: java.lang.IllegalStateException: Can't change container ID of fragment FragmentHomeController{408202a8 id=0x7f050010 HomeController}: was 2131034128 now 2131034132
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1751)
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1767)
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3117)
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.access$1600(ActivityThread.java:122)
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1009)
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.os.Handler.dispatchMessage(Handler.java:99)
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.os.Looper.loop(Looper.java:132)
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.main(ActivityThread.java:4028)
03-26 00:13:14.829: E/AndroidRuntime(30090): at java.lang.reflect.Method.invokeNative(Native Method)
03-26 00:13:14.829: E/AndroidRuntime(30090): at java.lang.reflect.Method.invoke(Method.java:491)
03-26 00:13:14.829: E/AndroidRuntime(30090): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
03-26 00:13:14.829: E/AndroidRuntime(30090): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
03-26 00:13:14.829: E/AndroidRuntime(30090): at dalvik.system.NativeStart.main(Native Method)
03-26 00:13:14.829: E/AndroidRuntime(30090): Caused by: java.lang.IllegalStateException: Can't change container ID of fragment FragmentHomeController{408202a8 id=0x7f050010 HomeController}: was 2131034128 now 2131034132
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.BackStackRecord.doAddOp(BackStackRecord.java:338)
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.BackStackRecord.add(BackStackRecord.java:316)
03-26 00:13:14.829: E/AndroidRuntime(30090): at eu.areamobile.apps.sfa.activity.HomeActivity.reattach(HomeActivity.java:340)
03-26 00:13:14.829: E/AndroidRuntime(30090): at eu.areamobile.apps.sfa.activity.HomeActivity.customHideShowCreate(HomeActivity.java:253)
03-26 00:13:14.829: E/AndroidRuntime(30090): at eu.areamobile.apps.sfa.activity.HomeActivity.customHideShowCreate(HomeActivity.java:155)
03-26 00:13:14.829: E/AndroidRuntime(30090): at eu.areamobile.apps.sfa.activity.HomeActivity.onPostCreate(HomeActivity.java:66)
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.Instrumentation.callActivityOnPostCreate(Instrumentation.java:1111)
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1734)
Run Code Online (Sandbox Code Playgroud)
经过快速调试后,我注意到在Android 3.1上,FragmentTransaction.remove没有将要删除的片段的mContainerId设置为0,而在ICS上它可以正常工作.
有任何建议或解决方法吗?
sst*_*stn 19
我解决这个问题的方法是在保持状态的同时重新创建片段:
FragmentTransaction ft = mFragmentManager.beginTransaction();
ft.remove(old);
Fragment newInstance = recreateFragment(old);
ft.add(R.id.new_container, newInstance);
ft.commit();
Run Code Online (Sandbox Code Playgroud)
使用以下辅助函数:
private Fragment recreateFragment(Fragment f)
{
try {
Fragment.SavedState savedState = mFragmentManager.saveFragmentInstanceState(f);
Fragment newInstance = f.getClass().newInstance();
newInstance.setInitialSavedState(savedState);
return newInstance;
}
catch (Exception e) // InstantiationException, IllegalAccessException
{
throw new RuntimeException("Cannot reinstantiate fragment " + f.getClass().getName(), e);
}
}
Run Code Online (Sandbox Code Playgroud)
它适用于我,至少使用最新的支持库(r11),虽然我还没有测试太多.
额外的成本是将片段实例化两次.
Yan*_*kin 16
在尝试了类似问题的所有答案后,看起来我已经找到了解决问题的方法.
第一个问题 - 在尝试将片段添加到另一个容器之前,您必须提交并执行 remove transaction.谢谢你的回答
但这并不是每次都有效.第二个问题是后台堆栈.它以某种方式阻止了交易.
所以对我有用的完整代码如下:
manager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
manager.beginTransaction().remove(detailFragment).commit();
manager.executePendingTransactions();
manager.beginTransaction()
.replace(R.id.content, masterFragment, masterTag)
.add(R.id.detail, detailFragment, activeTag)
.commit();
Run Code Online (Sandbox Code Playgroud)
基于片段开发人员指南,其中指出:
如果在执行删除片段的事务时不调用 addToBackStack(),则该片段会在提交事务时被销毁,并且用户无法导航回该片段。然而,如果您在删除片段时调用 addToBackStack(),则片段将停止,并且如果用户导航回来,片段将恢复
所以我假设你的碎片对象在调用后被销毁
ft.remove(frag); //stacco il frammento dal container A
ft.commit();
Run Code Online (Sandbox Code Playgroud)
但你说它在 ICS 中有效,这很奇怪。为什么不尝试替换方法并看看会发生什么?
希望这可以帮助...
| 归档时间: |
|
| 查看次数: |
24074 次 |
| 最近记录: |