Хорошо, я наконец понял это:
Как было предложено выше, сначала я изменил создание фрагментов, чтобы они выполнялись программно, и добавил их в менеджер дочерних фрагментов, например:
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, но я заметил, что также будет вызываться OnCreateView старого Lhs/RhsFragment. Таким образом, после каждого переключения вкладок будет еще один вызов 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);
}
Теперь все работает отлично, как при переключении вкладок, так и при смене ориентации.
person
Brad Robinson
schedule
14.03.2013