Фрагмент onResume () & onPause() не вызывается на backstack
у меня есть несколько фрагментов внутри активности. По щелчку кнопки я начинаю новый фрагмент, добавляя его в backstack. Я, естественно, ожидал 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();
}
}
то, что я ожидал, было,
- при нажатии кнопки LoginFragment заменяется с
HomeFragment,onPause()на LoginFragment иonResume()of
HomeFragment вызывается - при нажатии кнопки Back HomeFragment выскочил и LoginFragment is
видел, иonPause()на HomeFragment иonResume()на LoginFragment
его вызывают.
то, что я получаю,
- при нажатии кнопки , HomeFragment правильно заменить
LoginFragment, onResume () of HomeFragment называется, но onPause()
из LoginFragment никогда не вызывается. - при нажатии назад,HomeFragment правильно выскакивает, чтобы показать
LoginFragment, onPause () of HomeFragment вызывается, но onResume()
из LoginFragment никогда не вызывается.
Is это нормальное поведение? Почему это onResume() на LoginFragment не вызывается, когда я нажмите кнопку Назад.
15 ответов:
фрагментов
onResume()илиonPause()будет вызываться только тогда, когда действияonResume()илиonPause()называется. Они плотно соединены сActivity.читать обработка раздела жизненного цикла фрагмента этой статьи.
- так как вы использовали
ft2.replace(),FragmentTransaction.remove()метод называется и тоLoginfragmentбудут удалены. См.этой. Так чтоonStop()наLoginFragmentбудет вызван вместоonPause(). (Как новый фрагмент полностью заменяет старый).- но так как у вас также используется
ft2.addtobackstack(), состояниеLoginfragmentбудет сохранено в виде пакета и при нажатии кнопки назад отHomeFragment,onViewStateRestored()будет называться с последующимonStart()ofLoginFragment. Так что в конце концовonResume()не назовешь.
Если вы действительно хотите заменить фрагмент В фрагмент вы должны использовать Вложенные Фрагменты.
в вашем коде вы должны заменить
final FragmentManager mFragmentmanager = getFragmentManager();С
final FragmentManager mFragmentmanager = getChildFragmentManager();
вот моя более надежная версия ответа гора (с использованием фрагментов.размер () ненадежен из-за того, что размер не уменьшается после того, как фрагмент выскочил)
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; }
у меня есть код очень похож на ваш, и если он работает 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(); } }
простые Не могу добавить фрагмент к фрагменту. Это должно произойти во фрагментарной активности. Я предполагаю, что вы создаете LoginFragment в FragmentActivity, поэтому для того, чтобы получить эту работу, вам нужно добавить HomeFragment через FragmentActivity, когда логин закрывается.
общий момент заключается в том, что вам нужен класс FragmentActivity, из которого вы добавляете каждый фрагмент в FragmentManager. Это не возможно чтобы сделать это внутри фрагмента класс.
Если вы добавляете фрагмент в XML, вы не можете поменять их динамически. То, что происходит, они чрезмерно, поэтому они не стреляют, как можно было бы ожидать. Проблема задокументирована в этом вопросе. FragmenManager replace делает overlay
включите middle_fragment в FrameLayout, и загрузите его, как показано ниже, и ваши события будут срабатывать.
getFragmentManager().beginTransation(). add(R.id.middle_fragment, new MiddleFragment()).commit();
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 } } });но будьте осторожны, если видно более одного фрагмента
что я делаю в фрагменте ребенка:
@Override public void onDetach() { super.onDetach(); ParentFragment pf = (ParentFragment) this.getParentFragment(); pf.onResume(); }а затем переопределить onResume на ParentFragment
фрагмент всегда должен быть встроен в действие, и жизненный цикл фрагмента напрямую зависит от жизненного цикла действия хоста. Например, когда действие приостановлено, все фрагменты в нем, а когда действие уничтожено, все фрагменты
Вы можете попробовать это,
Шаг 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(); }
onPause()метод работает в классе activity вы можете использовать:public void onDestroyView(){ super.onDestroyView }С той же целью..
выполните следующие действия, и вы получите необходимый ответ
1-для обоих фрагментов создайте новый абстрактный Родительский.
2-добавить пользовательский абстрактный метод, который должен быть реализован ими обоими.
3-вызовите его из текущего экземпляра перед заменой на второй.
на основе ответа @Gor я писал подобное в Котлин. Поместите этот код в
onCreate()действия. Он работает для одного видимого фрагмента. Если у вас естьViewPagerС фрагментами, он будет вызыватьViewPagerфрагмент, а не предыдущий.supportFragmentManager.addOnBackStackChangedListener { supportFragmentManager.fragments.lastOrNull()?.onResume() }после прочтения https://medium.com/@elye.project/puzzle-fragment-stack-pop-cause-issue-on-toolbar-8b947c5c07c6 я понял, что во многих ситуациях было бы лучше прикреплять новые фрагменты с помощью
replace, а неadd. Так что нужда вonResumeв некоторых случаях исчезнет.
при создании фрагментной транзакции обязательно добавьте следующий код.
// 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);также убедитесь, чтобы зафиксировать транзакцию после добавления его в backstack
Comments