片段onResume()&onPause()不在栈上调用

我在活动中有多个片段。 在一个button上单击我开始一个新的片段,将其添加到后台堆栈。 我自然希望调用当前Fragment和onResume()的新片段的onPause()方法。 那么它不会发生。

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. 当单击button时, LoginFragmentLoginFragment的HomeFragmentonPause()所取代, HomeFragment的 onResume()被调用
  2. 当按下后, HomeFragment被调出, LoginFragment被看到, HomeFragment的 onPause()LoginFragment的 onResume()被调用。

我得到的是,

  1. 当单击button时, HomeFragment正确replaceLoginFragmentHomeFragment的 onResume()被调用,但LoginFragment的 onPause()永远不会被调用。
  2. 当返回按下时, HomeFragment正确popup以显示LoginFragmentHomeFragment的 onPause()被调用,但是LoginFragment的 onResume()永远不会被调用。

这是正常的行为? 为什么按下后退button时, LoginFragment的 onResume()没有被调用。

仅当调用Activity onResume()onPause()时才会调用片段onResume()onPause() 。 他们与Activity紧密相连。

阅读处理本文的片段生命周期部分 。

  • 既然你已经使用了ft2.replace()FragmentTransaction.remove()方法被调用, Loginfragment将被移除。 参考这个 。 所以LoginFragment onStop()将被调用,而不是onPause() 。 (因为新的片段完全取代了旧的片段)。
  • 但是由于您也使用了ft2.addtobackstack() ,所以ft2.addtobackstack()的状态将被保存为一个包,当您从HomeFragment点击返回button时, onViewStateRestored()将被调用,然后onStart() LoginFragment onStart() 。 所以最终onResume()将不会被调用。

如果你真的想replace其他片段内的片段,你应该使用嵌套片段 。

在你的代码中,你应该replace

 final FragmentManager mFragmentmanager = getFragmentManager(); 

 final FragmentManager mFragmentmanager = getChildFragmentManager(); 

这是我的更强大的版本的Gor的答案(使用fragments.size()是不可靠的,因为大小不会减less后,片段被popup)

 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中发生。 我假设你是在FragmentActivity中创buildLoginFragment,所以为了得到这个工作,你需要在loginclosures时通过FragmentActivity添加HomeFragment。

一般的观点是,你需要一个FragmentActivity类,从每个Fragment添加到FragmentManager。 在Fragment类中不可能做到这一点。

如果以XML格式添加片段,则不能dynamic交换。 会发生什么,他们过度,所以他们的事件不会像预期的那样开火。 这个问题logging在这个问题。 FragmenManagerreplace使覆盖

把middle_fragment变成一个FrameLayout,并像下面一样加载,你的事件将会触发。

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

我有一个非常类似于你的代码,如果它的作品onPause()和onResume()。 改变片段时,这些function分别被激活。

代码片段:

  @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"); } 

logging片段变化时:

 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(); } } 

片段必须始终embedded到活动中,片段的生命周期直接受到宿主活动生命周期的影响。 例如,当活动暂停时,其中的所有片段也是如此,当活动被破坏时,所有片段也是如此

你可以试试这个,

第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 } 

为了同样的目的..

在创build片段事务时,请确保添加以下代码。

 // 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); 

另外确保在将其添加到后台堆栈之后提交该事务