Я нашел много случаев аналогичного вопроса о SO, но, к сожалению, ни один ответ не отвечает моим требованиям.
У меня есть разные макеты для портретной и альбомной ориентации, и я использую задний стек, который и мешает мне использовать setRetainState()
трюки, используя процедуры изменения конфигурации.
Я показываю определенную информацию пользователю в TextViews, которая не сохраняется в обработчике по умолчанию. При написании моего приложения исключительно с использованием Activity, хорошо работало следующее:
TextView vstup;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.whatever);
vstup = (TextView)findViewById(R.id.whatever);
/* (...) */
}
@Override
public void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
state.putCharSequence(App.VSTUP, vstup.getText());
}
@Override
public void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
vstup.setText(state.getCharSequence(App.VSTUP));
}
С Fragment
s это работает только в очень специфических ситуациях. В частности, ужасно ломается замена фрагмента, помещение его в задний стек, а затем вращение экрана во время показа нового фрагмента. Из того, что я понял, старый фрагмент не получает вызова onSaveInstanceState()
при замене, но остается каким-то образом связанным с Activity
и этот метод вызывается позже, когда его View
больше не существует, так что ищите любой из моих TextView
результатов в NullPointerException
.
Кроме того, я обнаружил, что сохранение ссылки на my TextViews
не является хорошей идеей с Fragment
s, даже если это было нормально с Activity
s. В этом случае onSaveInstanceState()
фактически сохраняет состояние, но проблема появляется снова, если я поворачиваю экран дважды, когда фрагмент скрыт, так как его onCreateView()
не вызывают в новом экземпляре.
Я думал о сохранении состояния в onDestroyView()
некотором Bundle
элементе-члене класса (на самом деле это больше данных, а не только один TextView
) и сохранении этого в, onSaveInstanceState()
но есть и другие недостатки. В первую очередь, если фрагмент в настоящее время показано, порядок вызова двух функций восстанавливается, так что я должен был бы счет для двух различных ситуаций. Должно быть более чистое и правильное решение!
Ответы:
Чтобы правильно сохранить состояние экземпляра
Fragment
вы должны сделать следующее:1. Во фрагменте сохраните состояние экземпляра, переопределив
onSaveInstanceState()
и восстановив вonActivityCreated()
:2. И важный момент : в упражнении вы должны сохранить экземпляр фрагмента в
onSaveInstanceState()
и восстановить егоonCreate()
.Надеюсь это поможет.
источник
Это способ, которым я сейчас пользуюсь ... он очень сложный, но, по крайней мере, он обрабатывает все возможные ситуации. На случай, если кому-то интересно.
Кроме того , всегда есть возможность сохранить данные, отображаемые в пассивных
View
s в переменных и с помощьюView
s только для их отображения, синхронизируя две вещи. Я не считаю последнюю часть очень чистой, хотя.источник
A
иB
, гдеA
в данный момент находится в backstack иB
виден, вы теряете состояниеA
(невидимое 1) если повернуть дисплей дважды . Проблема в том, чтоonCreateView()
не вызывается только в этом сценарииonCreate()
. Итак, позжеonSaveInstanceState()
нет никаких представлений, от которых можно спасти государство. Нужно было бы сохранить, а затем сохранить переданное состояниеonCreate()
.App.VSTUP
иApp.STAV
являются строковые метки, которые представляют собой объекты , они пытаются получить. Пример:savedState = savedInstanceState.getBundle(savedGamePlayString);
илиsavedState.getDouble("averageTime")
В последней библиотеке поддержки ни одно из обсуждавшихся здесь решений больше не требуется. Вы можете играть со своими
Activity
фрагментами так, как вам нравится, используяFragmentTransaction
. Просто убедитесь, что ваши фрагменты могут быть идентифицированы либо с помощью идентификатора или тега.Фрагменты будут восстановлены автоматически до тех пор, пока вы не попытаетесь воссоздать их при каждом вызове
onCreate()
. Вместо этого вы должны проверить, неsavedInstanceState
является ли оно нулевым, и найти старые ссылки на созданные фрагменты в этом случае.Вот пример:
Однако обратите внимание, что в настоящее время существует ошибка при восстановлении скрытого состояния фрагмента. Если вы скрываете фрагменты в своей деятельности, в этом случае вам нужно будет восстановить это состояние вручную.
источник
FragmentPagerAdapter
илиFragmentStatePagerAdapter
. Если вы посмотрите на кодFragmentStatePagerAdapter
, например, вы увидите, чтоrestoreState()
метод восстанавливает фрагменты из того, чтоFragmentManager
вы передали в качестве параметра при создании адаптера.Я просто хочу дать решение, которое я придумал, которое обрабатывает все случаи, представленные в этом посте, которые я получил от Vasek и devconsole. Это решение также обрабатывает особый случай, когда телефон поворачивается более одного раза, а фрагменты не видны.
Здесь я храню пакет для дальнейшего использования, так как onCreate и onSaveInstanceState - единственные вызовы, которые выполняются, когда фрагмент не виден
Так как destroyView не вызывается в особой ситуации вращения, мы можем быть уверены, что если оно создает состояние, мы должны его использовать.
Эта часть была бы такой же.
Теперь вот сложная часть. В моем методе onActivityCreated я создаю экземпляр переменной myObject, но вращение происходит по onActivity и onCreateView не вызывается. Поэтому myObject будет нулевым в этой ситуации, когда ориентация поворачивается более одного раза. Я обхожу это путем повторного использования того же пакета, который был сохранен в onCreate, что и выходящий пакет.
Теперь, где бы вы ни хотели восстановить состояние, просто используйте комплект saveState
источник
Благодаря DroidT я сделал это:
Я понимаю, что если фрагмент не выполняет onCreateView (), его представление не создается. Таким образом, если фрагмент в заднем стеке не создает свои представления, я сохраняю последнее сохраненное состояние, в противном случае я создаю свой собственный пакет с данными, которые я хочу сохранить / восстановить.
1) Расширить этот класс:
2) В вашем фрагменте вы должны иметь это:
3) Например, вы можете вызвать hasSavedState в onActivityCreated:
источник
источник