Фрагмент 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();
}
}


то, что я ожидал, было,




  1. при нажатии кнопки LoginFragment заменяется с
    HomeFragment,onPause() на LoginFragment и onResume() of
    HomeFragment вызывается

  2. при нажатии кнопки Back HomeFragment выскочил и LoginFragment is
    видел, и onPause() на HomeFragment и onResume() на LoginFragment
    его вызывают.


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




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

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


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

542   15  

15 ответов:

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

читать обработка раздела жизненного цикла фрагмента этой статьи.

  • так как вы использовали ft2.replace(),FragmentTransaction.remove() метод называется и то Loginfragment будут удалены. См.этой. Так что onStop() на LoginFragment будет вызван вместо onPause(). (Как новый фрагмент полностью заменяет старый).
  • но так как у вас также используется ft2.addtobackstack(), состояние Loginfragment будет сохранено в виде пакета и при нажатии кнопки назад от HomeFragment, onViewStateRestored() будет называться с последующим onStart() of LoginFragment. Так что в конце концов 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

    Ничего не найдено.