Зачем мне когда-либо хотеть `setRetainInstance (false)`? – Или – Правильный способ обработки вращения устройства

Пожалуйста, поправьте меня, если я ошибаюсь в этом. Это своего рода уточняющий вопрос, поскольку я не видел его явно написанным где-либо.

В Android 4 вы можете вызвать setRetainInstance(true) на Fragment чтобы при изменении конфигурации (что в основном означает вращение устройства) объект java Fragment не уничтожается, а новый экземпляр его не создается. То есть экземпляр сохраняется.

Это намного более разумно и менее бесит, чем в Android 1-3, так как вам не нужно иметь дело с onRetainNonConfiguration State Instance() и onRetainNonConfiguration все ваши данные, чтобы он мог быть передан в новый экземпляр Fragment (или Activity ) только для Снова разделяться. Это в основном то, что вы ожидали бы, и, возможно, как он должен был работать с Activity s с самого начала.

С setRetainInstance(true) представление также воссоздается ( onCreateView() ), как и следовало ожидать. И я предполагаю (не проверено), что разрешение ресурсов ( layout против layout-land ) работает.

Поэтому мой вопрос двоякий:

  1. Почему это было не так с Activities с самого начала.
  2. Почему это не по умолчанию? Есть ли какая-либо причина, по которой вы действительно хотите, чтобы ваш Fragment был бесцельно уничтожен и воссоздан по ротации? Потому что я не могу думать ни о чем.

редактировать

Чтобы уточнить, как я это сделаю:

 class MyFragment extends Fragment { // All the data. String mDataToDisplay; // etc. // All the views. TextView mViewToDisplayItIn; // etc. @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); mDataToDisplay = readFromSomeFileOrWhatever(); // Ignoring threading issues for now. } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.my_fragment, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { // At this point if mViewToDisplayItIn was not null, the old one will be GC'd. mViewToDisplayItIn = view.findViewById(R.id.the_text_view); mViewToDisplayItIn.setText(mDataToDisplay); } // Optionally: @Override public void onDestroyView() { // All the view (and activity) to be GC'd. mViewToDisplayItIn = null; } } 

Solutions Collecting From Web of "Зачем мне когда-либо хотеть `setRetainInstance (false)`? – Или – Правильный способ обработки вращения устройства"

Так что при изменении конфигурации (что в основном означает вращение устройства)

И изменение языка, изменение SIM-карты, изменение размера шрифта по умолчанию, подключение или удаление внешней клавиатуры, установка устройства на док-станцию ​​или удаление его с того же самого и т. Д.

Вам не нужно иметь дело с onRetainNonConfigurationState ()

Это onRetainNonConfigurationInstance() .

Объедините все ваши данные, чтобы он мог быть передан в новый экземпляр фрагмента (или Activity) только для повторного разделения

Ваши данные уже должны быть «связаны» (например, экземпляр частного статического внутреннего класса), и поэтому его не нужно «связывать» или «разделять». Кроме того, часто это не должно быть «все ваши данные», если вы не являетесь поклонником утечек памяти.

И я предполагаю (не проверено), что разрешение ресурсов (макет против макета-земли) работает.

Верный.

Есть ли какая-либо причина, по которой вы действительно хотите, чтобы ваш фрагмент был бесцельно уничтожен и воссоздан по ротации?

Конечно.

Как вы заметили, все виджеты воссозданы, поэтому данные, привязанные к виджетам, не только не нужны для сохранения. Если вы специально не сбросите те, которые имеют значение null на сохраненном фрагменте, до onCreateView() пор, пока не будет onCreateView() , эти члены данных будут onCreateView() в старые виджеты, которые будут удерживать старый экземпляр активности, что предотвратит удаление этого старого экземпляра активности собраны. onCreateView() , onCreateView() не будет вызываться до тех пор, пока фрагмент не будет повторно отображаться, что может не быть достаточно долго (фрагмент не используется в новой ориентации, или фрагмент для некоторой страницы в ViewPager что Пользователь посетил в старой ориентации, но не пересматривает новую ориентацию и т. Д.). Это означает, что сохраненный фрагмент может содержать старый объект активности в течение значительного периода времени. В зависимости от того, что еще может занимать эта деятельность (например, большие объекты Bitmap ), это может быть плохо.

Точно так же фрагмент, который сам содержит большие данные, где этот фрагмент может быть использован или не может использоваться после изменения конфигурации, является тем, который не следует сохранять.

Кроме того, будут фрагменты, которые просто не нужно ничего сохранять (например, все данные заполняются Loaders , которые уже знают об изменениях конфигурации и обрабатывают их соответственно).

И так далее.

По умолчанию фрагменты, которые не сохраняются, являются самым безопасным способом действий в отношении проблем сбора мусора. Вы можете выбрать, чтобы некоторые фрагменты были сохранены, но тогда на вас лежит бремя , чтобы убедиться, что вы не задираете себя, делая это.

Я не знаю ответа на первый вопрос. С самого начала это должно было быть так. Думаю, кто-то в Google подумал, что они действительно сообразительны в этой схеме.

Второй вопрос, однако, намного проще. Это не по умолчанию, потому что это не то, что разработали Android. Разработчики Android знают, что экземпляр умирает при вращении и ожидает его. Изменение значения по умолчанию привело бы к тому, что многие разработчики действительно разозлились.