碎片中的碎片

我想知道这是否真的是 Android API 中的一个 bug:

我有一个这样的设置:

┌----┬---------┐
|    |         |
|  1 |    2    |
|    |┌-------┐|
|    ||       ||
|    ||   3   ||
└----┴┴-------┴┘
  1. 是一个菜单,它在右窗格中加载片段 # 2(搜索屏幕)。
  2. 是一个搜索屏幕,其中包含片段 # 3,这是一个结果列表。
  3. 结果列表可以在几个地方使用(包括作为功能性高级片段使用)。

这个功能在手机上运行得非常好(其中1、2和3是 ActivityFragment)。

但是,当我使用这个代码时:

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Fragment frag = new FragmentNumber2();
if(toLoad != null) frag.setArguments(toLoad);
transaction.replace(R.id.rightPane, frag);
transaction.commit();

其中 R.id.leftPaneR.id.rightPane是水平线性布局的 <fragment>

我的理解是,上面的代码删除了驻留的片段,然后用一个新的片段替换它。太棒了... ... 显然这不会发生,因为当这段代码第二次运行时,会出现以下异常:

07-27 15:22:55.940: ERROR/AndroidRuntime(8105): Caused by: java.lang.IllegalArgumentException: Binary XML file line #57: Duplicate id 0x7f080024, tag null, or parent id 0x0 with another fragment for FragmentNumber3

这是因为 FragmentNumber3的容器已经被复制,不再具有唯一的 ID。最初的碎片还没有被销毁(?)在添加新的之前(在我看来,这意味着它不是 被取代了)。

有人能告诉我这是否可能(这个答案表示不可能) ,或者这是一个错误?

141925 次浏览

目前不支持嵌套的片段。试图将一个片段放入另一个片段的 UI 中将导致未定义的和可能的破坏行为。

更新 : 从安卓4.2开始的嵌套片段 支持(以及安卓支持库 rev 11) : < a href = “ http://developer.Android.com/about/version/Android-4.2.html # NestedFragments”rel = “ norefrer”> http://developer.Android.com/about/versions/Android-4.2.html#nestedfragments

注意 (根据 这份文件) : “ 注意: 当一个布局包含 <fragment>时,您不能将其膨胀为片段。嵌套的片段只有在动态添加到片段时才受支持。

我有一个我正在开发的应用程序,它的布局类似于动作栏中的标签,可以启动片段,其中一些片段包含多个嵌入的片段。

当我尝试运行应用程序时,也出现了同样的错误。看起来,如果您在 xml 布局中实例化片段,在选项卡未被选中之后,然后重新选择,那么我将得到充气器错误。

我解决了这个问题,用 Linearlayouts 替换 xml 中的所有片段,然后使用片段管理器/片段事务来实例化片段,至少目前在测试级别上,一切似乎都正常工作。

希望这能帮到你。

. . 你可以在父片段的 destroyview方法中清理你的嵌套片段:

@Override
public void onDestroyView() {


try{
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();


transaction.remove(nestedFragment);


transaction.commit();
}catch(Exception e){
}


super.onDestroyView();
}

Android 4.2及更高版本支持嵌套片段

Android 支援图书馆现在也支持 嵌套的碎片,因此您可以在 Android 1.6或更高版本上实现嵌套的片段设计。

要嵌套一个片段,只需对要在其中添加片段的片段调用 GetChildFragmentManager ()。这将返回一个 FragmentManager,您可以像通常在顶级活动中那样使用它来创建片段事务。例如,下面是一些代码,它们从现有的片段类中添加了一个片段:

Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();

要了解关于嵌套片段的更多信息,请阅读以下教程
第一部分
第二部分
第三部分 < br >

这里是一个讨论 嵌套片段的最佳实践的 SO 帖子。

我也遇到过同样的问题,已经为此挣扎了几天,我发现克服这个问题最简单的方法就是在选择/取消选择时使用 fragment.hide ()/fragment.show ()。

public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft)
{
if (mFragment != null)
ft.hide(mFragment);
}

当屏幕旋转发生时,所有的父代和子代片段将被正确销毁。

这种方法还有一个额外的优点——使用 hide ()/show ()不会导致片段视图失去其状态,因此不需要为 ScrollView 恢复以前的滚动位置。

问题是,我不知道在不可见的情况下不分离片段是否正确。我认为 TabListener 的官方示例是基于这样一种思想设计的: 片段是可重用的,你不应该用它们来污染内存。然而,我认为如果你只有几个标签,并且你知道用户会频繁地在它们之间切换,那么让它们与当前活动保持连接是合适的。

我想听听更有经验的开发人员的意见。

如果您发现您的嵌套片段没有被删除或被复制(例如,在活动重新启动,在屏幕旋转)尝试改变:

transaction.add(R.id.placeholder, newFragment);

transaction.replace(R.id.placeholder, newFragment);

如果上面说的没用,试试看:

Fragment f = getChildFragmentManager().findFragmentById(R.id.placeholder);


FragmentTransaction transaction = getChildFragmentManager().beginTransaction();


if (f == null) {
Log.d(TAG, "onCreateView: fragment doesn't exist");
newFragment= new MyFragmentType();
transaction.add(R.id.placeholder, newFragment);
} else {
Log.d(TAG, "onCreateView: fragment already exists");
transaction.replace(R.id.placeholder, f);
}
transaction.commit();

学习 给你