好的,我终于想通了:
如上所述,首先我将片段创建更改为以编程方式完成,并将它们添加到子片段管理器中,如下所示:
public override View OnCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstance)
{
var view = inflater.Inflate(Resource.Layout.MyView, viewGroup, false);
// Add fragments to the child fragment manager
// DONT DO THIS, SEE BELOW
var tx = ChildFragmentManager.BeginTransaction();
tx.Add(Resource.Id.lhs_fragment_frame, new LhsFragment());
tx.Add(Resource.Id.rhs_fragment_frame, new RhsFragment());
tx.Commit();
return view;
}
正如预期的那样,每次我切换选项卡时,都会创建一个额外的 Lhs/RhsFragment 实例,但我注意到旧的 Lhs/RhsFragment 的 OnCreateView 也会被调用。因此,在每次切换选项卡之后,都会再调用一次 OnCreateView。切换选项卡 10 次 = 11 次调用 OnCreateView。这显然是错误的。
查看 FragmentTabHost 的源代码,我可以看到它只是在切换选项卡时分离并重新附加选项卡的内容片段。似乎父片段的 ChildFragmentManager 将子片段保留在周围,并在重新附加父片段时自动重新创建它们的视图。
因此,我将片段的创建移至 OnCreate,并且仅当我们没有从保存状态加载时:
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
if (savedInstanceState == null)
{
var tx = ChildFragmentManager.BeginTransaction();
tx.Add(Resource.Id.lhs_fragment_frame, new LhsFragment());
tx.Add(Resource.Id.rhs_fragment_frame, new RhsFragment());
tx.Commit();
}
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstance)
{
// Don't instatiate child fragments here
return inflater.Inflate(Resource.Layout.MyView, viewGroup, false);
}
这修复了附加视图的创建和切换选项卡现在基本上可以工作了。
下一个问题是保存和恢复视图状态。在子片段中,我需要保存和恢复当前选定的项目。原来我有这样的东西(这是子片段的 OnCreateView)
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance)
{
var view = inflater.Inflate(Resource.Layout.CentresList, container, false);
// ... other code ommitted ...
// DONT DO THIS, SEE BELOW
if (savedInstance != null)
{
// Restore selection
_selection = savedInstance.GetString(KEY_SELECTION);
}
else
{
// Select first item
_selection =_items[0];
}
return view;
}
这样做的问题是选项卡主机在切换选项卡时不会调用 OnSaveInstanceState。相反,子片段保持活动状态,它的 _selection 变量可以单独放置。
所以我将管理选择的代码移到了 OnCreate:
public override void OnCreate(Bundle savedInstance)
{
base.OnCreate(savedInstance);
if (savedInstance != null)
{
// Restore Selection
_selection = savedInstance.GetString(BK_SELECTION);
}
else
{
// Select first item
_selection = _items[0];
}
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance)
{
// Don't restore/init _selection here
return inflater.Inflate(Resource.Layout.CentresList, container, false);
}
现在,无论是切换选项卡还是更改方向,这一切似乎都运行良好。