2015-11-08 2 views
3

Я хотел понять взаимодействие между жизненным циклом деятельности и жизненным циклом фрагмента в Android, поэтому я решил начать новый проект и скопировать код с this page.
Я тогда подумал, что для улучшения моего понимания было бы полезно протестировать его на планшете, переключить его ориентацию и посмотреть, что это произойдет (хотя, возможно, оно не предназначалось для этого). Через LogCat я отслеживал главных событий, которые обожженных как на деятельности и на фрагменте страны, например, в деятельности OnCreate я пишу:Жизненный цикл скрытого фрагмента

Log.d("TAG", "Activity: 1.onCreate"); 

Это то, что я получаю, когда я начинаю с точки зрения портретного а затем повернуть:

TAG: активность: 1.onCreate
TAG: активность: 2.onStart
TAG: ## ContryFrag: 1.onAttach
TAG: ## ContryFrag: 2.onCreateView
TAG: ## ContryFrag: 3.onStart
TAG: Активность: 3.onResume
TAG: ## ContryFrag: 4.onResume
TAG: Активность: -3.onPause
TAG: ## ContryFrag: -4 .onPause
TAG: активность: -2.onStop
TAG: ## ContryFrag: -3.onStop
TAG: активность: -1.onDestroy
TAG: ## ContryFrag: -2.onDestroyView
TAG: ## ContryFrag: -1.onDetach
TAG: Деятельность: 1.onCreate
TAG: ## ContryFrag: 1.onAttach
TAG: ## ContryFrag: 1.onAttach
TAG: ## ContryFrag: 2.onCreateView
TAG: Активность: 2.onStart
TAG: ## ContryFrag: 2 .onCreateView
TAG: ## ContryFrag: 3.onStart
TAG: ## ContryFrag: 3.onStart
TAG: активность: 3.onResume
TAG: ## ContryFrag: 4.onResume
TAG: ## ContryFrag: 4.onResume

Кажется, что фрагмент, который был добавлен через FragmentManager в портретном представлении, по-прежнему воссоздается после вращения, несмотря на то, что он был отсоединен раньше. Цепочка событий для ее возобновления выполняется снова, даже если она не будет отображаться.
Можете ли вы помочь мне понять, что здесь происходит?

EDIT

Когда я проверяю, если фрагмент isInLayout()

Log.d("TAG", "## ContryFrag: 1.onAttach /" + isInLayout()); 

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

TAG: Активность: 1.onCreate
TAG: ## ContryFrag: 1.onAttach/ложь
TAG: ## ContryFrag: 1.onAttach/верно
TAG: ## ContryFrag: 2.onCreateView/верно
TAG: Активность: 2.onStart
TAG: ## ContryFrag: 2.onCreateView/ложные
TAG: ## ContryFrag: 3.onStart/ложь
TAG: ## ContryFrag: 3.onStart/верно
TAG: активность: 3.onResume
TAG: ## ContryFrag: 4.onResume/ложь
TAG: ## ContryFrag: 4.onResume/true

EDIT 2

Это фиктивный код, который я использовал, чтобы получить onSelectedCountry (Струнный страна), которая не предоставляется:

public void onSelectedCountry(String country) 
{ 
    String[] x = {country, "city0", "city1", "city2", "city3", "city4", "city5"}; 
    adapter.clear(); 
    adapter.addAll(x); 
} 

EDIT 3

Вот my code. Извините за задержку, это был первый раз, когда я использовал github.

+0

Возможно, это из-за вашего журнала. Проверьте это в своем «Городском фрагменте». В режиме «пейзаж» я думаю, что фрагмент «city» и фрагмент «country» записывают одни и те же вещи. –

+0

Вы хотите сказать, что, возможно, код, отправляющий сообщения в logcat, также называется фрагментом City? Нет, я использовал код только для основного actvity и фрагментации страны. –

+0

Лучше, если вы разместите код в своем сообщении для удобства. В опубликованной ссылке не отображается весь код. Например, есть ли код для Activity.onStart()? –

ответ

3

После того, как вы добавили Fragment в FragmentManager, он остается там до тех пор, пока вы не удалите его вручную или до тех пор, пока Activity не закончится окончательно. (Перезапуск Activity, например, то, что происходит, когда устройство вращается, не приводит к его завершению)

Вращение устройства не очищает фрагменты. Если вы создаете новый Fragment и добавить его в FragmentManager в любое время в Activity Lifecycle без первой проверки, если Fragment уже существует в FragmentManager, вы просто добавить новый Fragment каждый раз, когда вы делаете что-то, что заставляет Activity быть перезапущен ,

Например, этот код должен содержать только одну копию фрагмента.

protected void onResume() { 

    String TAG = "COUNTRYFRAG"; 

    CountryFrag f = (CountryFrag) getSupportFragmentManager().findFragmentByTag(TAG); 

    if (f == null) { 
     f = new CountryFrag(); 
     getSupportFragmentManager().beginTransaction() 
       .add(f, TAG) 
       .commit(); 
    } 

    int count = getSupportFragmentManager().getFragments().size(); 
    Log.v("FRAGS", "There are " + count + "fragments in the fragment manager."); 

} 

пока этот будет добавлять новый при каждом повороте устройства.

protected void onResume() { 

    String TAG = "COUNTRYFRAG"; 

     CountryFrag f = new CountryFrag(); 
     getSupportFragmentManager().beginTransaction() 
       .add(f, TAG) 
       .commit(); 

    int count = getSupportFragmentManager().getFragments().size(); 
    Log.v("FRAGS", "There are " + count + "fragments in the fragment manager."); 

} 

Код по ссылке, похоже, использует присутствие savedInstanceState, чтобы определить, следует ли добавить фрагмент, или для возврата из метода. Это ненадежно, поскольку вы не можете ничего сохранять в состоянии, и поэтому он всегда может быть нулевым. Лучше конкретно проверить, добавили ли вы Фрагмент.

i.e

if (savedInstanceState != null) 
      return; 
+0

Спасибо за вашу помощь. Так кажется, что когда действие начинается в портретном режиме, он добавляет CountryFragment через диспетчер фрагментов. Затем, после вращения в ландшафте, добавляется новый CountryFragment, потому что это требуется файлу xml-макета. Возможно, проверка на savedInstanceState не является лучшим способом избежать двойной вставки фрагментов, но в этом случае это не преступник. Несмотря на то, что менеджер фрагментов не добавил новый фрагмент, теперь у нас есть два объекта CountryFragments. Странно, что оба они прикреплены, созданы, начаты и возобновлены, даже если показан только один. –

+0

После поворота обратно в портретный режим у нас по-прежнему есть два объекта CountryFragments: первый и тот, который добавлен после первого поворота. Состояние saveInstanceState работает. Затем, если во второй раз в ландшафтном режиме он не будет изменен, никаких новых параметров CountryFragments не будет добавлено. Кажется, что есть встроенный механизм для сохранения от двойной вставки фрагментов из ресурсов компоновки, –

+0

Я не пытался исправить конкретный случай, на который вы ссылались, поскольку вы заявили, что не хотите этого. Мой ответ объяснял, почему вы видите поведение, которое вы видите, потому что добавляется несколько фрагментов из-за плохой проверки того, был ли ранее добавлен фрагмент. – Kuffs

0

Похоже, что вы не используете предыдущий экземпляр вашего фрагмента. Android продолжает сохранять макет Фрагмента и связанный с ним задний стек, когда действие перезапускается из-за изменения конфигурации. Похоже, что при воссоздании Деяния создается новый фрагмент. Попробуйте добавить следующий код в OnCreate вашей деятельности по:

@Override 
public void onCreate(Bundle savedInstanceState) { 

     ...  

    ContryFrag fragment = (ContryFrag) mFragmentManager.findFragmentById(R.id.fragment_container); 

    if (fragment == null) { 
     FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction(); 
     fragmentTransaction.add(R.id.fragment_container, new ContryFrag()); 
     fragmentTransaction.commit(); 
    } 
} 

И удалить код создания фрагмента.

+0

Надеюсь, он решит странное поведение – galvan

+0

Странное поведение не исчезло. Во всяком случае, моя цель состоит не в том, чтобы решить проблему, а в том, чтобы понять причину того, о чем я сообщал. Код доступен по ссылке, которую я разместил, она воспроизводима. –

0

Связанная статья содержит фрагменты, определенные в макете xml. Ваш код в github создает и добавляет фрагменты по коду. Вы используете их вместе?

+0

Код идентичен. Он создает и добавляет фрагменты кода или xml, в зависимости от его ориентации (пейзаж или портрет). –

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