Фрагмент onResume () & onPause () не вызывается в стопку

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

LoginFragment.java

 public class LoginFragment extends Fragment{ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.login_fragment, container, false); final FragmentManager mFragmentmanager = getFragmentManager(); Button btnHome = (Button)view.findViewById(R.id.home_btn); btnHome.setOnClickListener(new View.OnClickListener() { public void onClick(View view){ HomeFragment fragment = new HomeFragment(); FragmentTransaction ft2 = mFragmentmanager.beginTransaction(); ft2.setCustomAnimations(R.anim.slide_right, R.anim.slide_out_left , R.anim.slide_left, R.anim.slide_out_right); ft2.replace(R.id.middle_fragment, fragment); ft2.addToBackStack(""); ft2.commit(); } }); } @Override public void onResume() { Log.e("DEBUG", "onResume of LoginFragment"); super.onResume(); } @Override public void onPause() { Log.e("DEBUG", "OnPause of loginFragment"); super.onPause(); } } 

HomeFragment.java

 public class HomeFragment extends Fragment{ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.login_fragment, container, false); } @Override public void onResume() { Log.e("DEBUG", "onResume of HomeFragment"); super.onResume(); } @Override public void onPause() { Log.e("DEBUG", "OnPause of HomeFragment"); super.onPause(); } } 

Я ожидал, что,

  1. При нажатии кнопки LoginFragment заменяется на HomeFragment , onPause() из LoginFragment и onResume() HomeFragment
  2. Когда нажимается задняя часть, HomeFragment выставляется и появляется окно LoginFragment , и onPause() из HomeFragment и onResume() из LoginFragment .

То, что я получаю,

  1. Когда кнопка нажата, HomeFragment правильно заменяет LoginFragment , вызывается onResume () HomeFragment , но onPause () из LoginFragment никогда не вызывается.
  2. При возврате назад HomeFragment правильно отображается, чтобы открыть LoginFragment , onPause () HomeFragment вызывается , но onResume () из LoginFragment никогда не вызывается .

Это нормальное поведение? Почему onResume() из LoginFragment не получает вызов, когда я нажимаю кнопку «Назад».

Фрагменты onResume() или onPause() будут вызываться только при onResume() Activities onResume() или onPause() . Они тесно связаны с Activity .

Прочтите раздел «Обработка фрагментации фрагментов» этой статьи .

  • Так как вы использовали ft2.replace() , вызывается метод FragmentTransaction.remove() и будет удален Loginfragment . См. Это . Поэтому onStop() из LoginFragment будет вызываться вместо onPause() . (Поскольку новый фрагмент полностью заменяет старый).
  • Но так как вы также использовали ft2.addtobackstack() , состояние Loginfragment в Loginfragment будет сохранено в виде пакета, и когда вы нажмете кнопку «Назад» из HomeFragment , будет вызываться onViewStateRestored() , за которым следует onStart() из LoginFragment . Поэтому в конечном итоге onResume() не будет вызываться.

Если вы действительно хотите заменить фрагмент внутри другого фрагмента, вы должны использовать вложенные фрагменты .

В вашем коде вы должны заменить

 final FragmentManager mFragmentmanager = getFragmentManager(); 

с

 final FragmentManager mFragmentmanager = getChildFragmentManager(); 

Вот моя более надежная версия ответа Гора (использование fragments.size () ненадежно из-за того, что размер не уменьшается после выхода фрагмента)

 getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { if (getFragmentManager() != null) { Fragment topFrag = NavigationHelper.getCurrentTopFragment(getFragmentManager()); if (topFrag != null) { if (topFrag instanceof YourFragment) { //This fragment is being shown. } else { //Navigating away from this fragment. } } } } }); 

И метод getCurrentTopFragment:

 public static Fragment getCurrentTopFragment(FragmentManager fm) { int stackCount = fm.getBackStackEntryCount(); if (stackCount > 0) { FragmentManager.BackStackEntry backEntry = fm.getBackStackEntryAt(stackCount-1); return fm.findFragmentByTag(backEntry.getName()); } else { List<Fragment> fragments = fm.getFragments(); if (fragments != null && fragments.size()>0) { for (Fragment f: fragments) { if (f != null && !f.isHidden()) { return f; } } } } return null; } 

Вы просто не можете добавить фрагмент в фрагмент. Это должно произойти в FragmentActivity. Я предполагаю, что вы создаете LoginFragment в FragmentActivity, поэтому, чтобы получить эту работу, вам нужно добавить HomeFragment через FragmentActivity, когда логин закрывается.

Главное, что вам нужен класс FragmentActivity, из которого вы добавляете каждый фрагмент в FragmentManager. Это невозможно сделать внутри класса Fragment.

Если вы добавите фрагмент в XML, вы не сможете их динамически менять. Что происходит, они чрезмерно, поэтому события не срабатывают, как можно было бы ожидать. Этот вопрос задокументирован в этом вопросе. FragmenManager заменяет наложение

Поверните middle_fragment в FrameLayout и загрузите его, как показано ниже, и ваши события будут срабатывать.

 getFragmentManager().beginTransation(). add(R.id.middle_fragment, new MiddleFragment()).commit(); 

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

Вы можете попробовать это,

Шаг1: переопределите метод Tabselected в вашей деятельности

 @Override public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { // When the given tab is selected, switch to the corresponding page in // the ViewPager. try { if(MyEventsFragment!=null && tab.getPosition()==3) { MyEvents.fragmentChanged(); } } catch (Exception e) { } mViewPager.setCurrentItem(tab.getPosition()); } 

Шаг 2. Использование статического метода делает то, что вы хотите в своем фрагменте,

 public static void fragmentChanged() { Toast.makeText(actvity, "Fragment Changed", Toast.LENGTH_SHORT).show(); } 
 getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { List<Fragment> fragments = getFragmentManager().getFragments(); if (fragments.size() > 0 && fragments.get(fragments.size() - 1) instanceof YoureFragment){ //todo if fragment visible } else { //todo if fragment invisible } } }); 

Но будьте осторожны, если видится более одного фрагмента

onPause() работает в классе активности, который вы можете использовать:

 public void onDestroyView(){ super.onDestroyView } 

С той же целью ..

У меня есть код, очень похожий на ваш, и если он работает onPause () и onResume (). При изменении фрагмента эти функции активируются соответственно.

Код в фрагменте:

  @Override public void onResume() { super.onResume(); sensorManager.registerListener(this, proximidad, SensorManager.SENSOR_DELAY_NORMAL); sensorManager.registerListener(this, brillo, SensorManager.SENSOR_DELAY_NORMAL); Log.e("Frontales","resume"); } @Override public void onPause() { super.onPause(); sensorManager.unregisterListener(this); Log.e("Frontales","Pause"); } 

Лог при изменении фрагмента:

 05-19 22:28:54.284 2371-2371/madi.cajaherramientas E/Frontales: resume 05-19 22:28:57.002 2371-2371/madi.cajaherramientas E/Frontales: Pause 05-19 22:28:58.697 2371-2371/madi.cajaherramientas E/Frontales: resume 05-19 22:29:00.840 2371-2371/madi.cajaherramientas E/Frontales: Pause 05-19 22:29:02.248 2371-2371/madi.cajaherramientas E/Frontales: resume 05-19 22:29:03.718 2371-2371/madi.cajaherramientas E/Frontales: Pause 

Фрагмент onCreateView:

 View rootView; public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.activity_proximidad, container, false); ButterKnife.bind(this,rootView); inflar(); setTextos(); return rootView; } 

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

 @Override public void onBackPressed() { int count = getFragmentManager().getBackStackEntryCount(); if (count == 0) { super.onBackPressed(); } else { getFragmentManager().popBackStack(); } } 

При создании транзакции фрагмента обязательно добавьте следующий код.

 // Replace whatever is in the fragment_container view with this fragment, // and add the transaction to the back stack transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); 

Также убедитесь, что совершить транзакцию после добавления ее в стопку