2015-09-03 4 views
0

У меня есть одна активность и несколько фрагментов. Моя деятельность имеет список ящик, который я использую для переключения фрагментов и примерно выглядит следующим образом:Android Fragment onCreateView срабатывает, когда он не должен

public class MainActivity extends AppCompatActivity 
{ 
    private PreferencesFragment preferencesFragment; 
    private HomeFragment homeFragment; 

    private void selectMenuItem(position) 
    { 
     Fragment fragment = null; 
     switch (position) { 
      case 0: 
       if (preferencesFragment == null) { 
        preferencesFragment = new PreferencesFragment(); 
       } 
       fragment = preferencesFragment; 
      break; 
      case 1: 
       if (homeFragment == null) { 
        homeFragment = new HomeFragment(); 
       } 
       fragment = homeFragment; 
      break; 
     } 
     getFragmentManager() 
      .beginTransaction() 
      .replace(R.id.fragment_container, fragment) 
      .commit(); 

    } 
} 

Поэтому, когда я нажимаю на элемент списка ящик, selectMenuItem называется с правильным положением. Это загружает существующий фрагмент или создает новый, когда это необходимо. Проблема в том, что даже когда фрагмент уже существует, метод onCreateView запускается во Фрагментах. Я хочу сохранить состояние представления и только выполнить код в onCreateView один раз. Документы говорят об этом onCreateView:

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

Итак, почему он вызывается всякий раз, когда выполняется selectMenuItem? Я проверил, что на самом деле он не выполняет новый блок Fragment() и не загружает значение свойства. Как я могу поддерживать состояние своих фрагментов, когда я использую только одну активность?

savedInstanceState также является нулевым в onCreateViewMethod во Фрагментах. onSavedInstanceState никогда не запускается во Фрагментах.

ответ

0

Да, так работает жизненный цикл фрагмента. replace() удаляет все существующие фрагменты, а удаление фрагмента разрушает его представление. Повторное использование того же экземпляра Fragment в последующей транзакции фрагмента снова вызовет жизненный цикл с самого начала.

Как упоминает Иван в своих комментариях, onSaveInstanceState() запускается только при инициировании хостинговой активности onSaveInstanceState(), и просто замена фрагмента внутри действия оставляет действие незавершенным. Вы можете сохранить состояние самостоятельно, см., Например, android fragment- How to save states of views in a fragment when another fragment is pushed on top of it

Чтобы ваши фрагменты получали собранный мусор, не оставляйте ссылки на них.

+0

Спасибо, это имеет смысл. Я раньше не упоминал о них и просто использовал «New HomeFragment()»; каждый раз после нажатия на пункт меню. Однако onSaveInstanceState() никогда не вызывался на мои фрагменты. Любая идея почему? – jesper87

+1

'onSaveInstanceState()' не будет вызываться при удалении фрагмента из макета. Это происходит только тогда, когда вызывается функция 'onSaveInstanceState()' активности. В противном случае он сохраняет состояние как есть, если только активность не убита, и пока вы держитесь за ссылку на фрагмент, вы можете предположить, что переменные-члены остаются нетронутыми, только виды уничтожаются/воссоздаются (И это, конечно, означает, что «забудьте' null' ссылки члены мнения в 'onDestroyView()', если таковые имеются) –

+0

я добавил это мой фрагмент: '@Override общественного недействительными onSaveInstanceState (Bundle outState) { super.onSaveInstanceState (outState); Log.v (LOG_TAG, "onSaveInstanceState"); } ' Но это никогда не называется? У меня нет этого метода, переопределенного в моей деятельности. – jesper87

0

Если вы замените фрагмент другим фрагментом - виды будут уничтожены, это правильное поведение. Если вам действительно нужно избегать просмотра отдыха, вы можете использовать FragmentTransaction.hide(), но imho ваш нынешний подход прав, вы не знаете, будет ли пользователь когда-либо хотеть видеть PreferencesFragment, поэтому нет смысла в раздувающейся памяти с ненужными скрытыми видами.

Смежные вопросы