我在一个活动中有多个片段。在一个按钮点击我开始一个新的片段,添加到backstack。我自然希望调用当前Fragment的onPause()方法和新Fragment的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、LoginFragment的onPause()和onResume() HomeFragment被调用 当按下back键时,HomeFragment弹出,LoginFragment弹出 以及HomeFragment的onPause()和LoginFragment的onResume() 被调用。

我得到的是,

单击按钮时,HomeFragment被正确替换 LoginFragment, HomeFragment的onResume()被调用,但onPause()被调用 LoginFragment从来不被调用。 当向后按,HomeFragment是正确弹出显示 LoginFragment, HomeFragment的onPause()被调用,但onResume() 的LoginFragment从未被调用。

这是正常行为吗?为什么LoginFragment的onResume()没有被调用,当我按下返回按钮。


当前回答

你可以试试这个,

第一步:在你的活动中覆盖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()和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();
    }

 }

对我来说,原因是使用navGraph在片段之间切换

app:navGraph

像这样创建片段(在Kotlin中),然后调用所有的生命周期函数

val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.nav_host_fragment, fragment)
transaction.addToBackStack(null)
transaction.commit()

Since you have used ft2.replace(), FragmentTransaction.remove() method is called and the Loginfragment will be removed. Refer to this. So onStop() of LoginFragment will be called instead of onPause(). (As the new fragment completely replaces the old one). But since you have also used ft2.addtobackstack(), the state of the Loginfragment will be saved as a bundle and when you click back button from HomeFragment, onViewStateRestored() will be called followed by onStart() of LoginFragment. So eventually onResume() won't be called.

当一个片段出现/消失时,有两种可能的覆盖方法保证被调用。

Oncreateview /ondestroyview -当片段可见性改变时调用

Onpause /onresume -当应用程序被外部关闭或使用片段替换时调用

如果你想创建一个钩子,我这样做,你可以被通知,每当一个片段是关闭的,并捕捉任何一种情况,而不创建一个重复的调用,因为有时两者都可以被调用。

尝试扩展片段类,并在两个重写中添加一个布尔标志,这样就可以在不重复的情况下捕获open和close

基于@Gor的回答,我在Kotlin中写了类似的东西。将此代码放在活动的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中的需求将会消失。