219

アクティビティ内に複数のフラグメントがあります。ボタンをクリックすると、新しいフラグメントが開始され、バックスタックに追加されます。私は当然、現在の Fragment と新しい FragmentのonPause()メソッドが呼び出されることを期待していました。onResume()まあ、それは起こっていません。

ログインフラグメント.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置き換えられ、 LoginFragment呼び出され、HomeFragmentが呼び出されますonPause()onResume()
  2. 戻るを押すと、HomeFragmentがポップアウトされてLoginFragmentが表示されonPause()HomeFragmentLoginFragmentonResume()が 呼び出されます。

私が得ているのは、

  1. ボタンをクリックすると、HomeFragmentが LoginFragment を正しく置き換え 、 HomeFragmentのonResume () が呼び出されますが、 LoginFragment のonPause () は呼び出されません。
  2. 戻ると、HomeFragmentが正しくポップして LoginFragment が表示され、 HomeFragmentのonPause () が呼び出されますが、 LoginFragment の onResume() は呼び出されません。

これは正常な動作ですか?戻るボタンを押したときに LoginFragment が呼び出されないonResume()なぜですか。

4

20 に答える 20

199

フラグメントonResume()またはは、アクティビティまたはが呼び出されonPause()たときにのみ呼び出されます。それらは と密結合しています。onResume()onPause()Activity

この記事の「フラグメント ライフサイクルの処理」セクションをお読みください。

于 2013-04-27T13:55:01.720 に答える
23
  • を使用しているためft2.replace()FragmentTransaction.remove() メソッドが呼び出され、Loginfragmentが削除されます。これを参照してください。そのため、の代わりにonStop()ofLoginFragmentが呼び出されますonPause()。(新しいフラグメントが古いフラグメントを完全に置き換えるため)。
  • ただし、 も使用しているためft2.addtobackstack()、 の状態はLoginfragmentバンドルとして保存され、 から戻るボタンをクリックするとHomeFragmentonViewStateRestored()に続いてonStart()of が呼び出されLoginFragmentます。だから結局onResume()呼ばれない。
于 2013-04-27T13:45:07.710 に答える
17

これがGorの答えのより堅牢なバージョンです(フラグメントがポップされた後にサイズが減少しないため、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;
}
于 2016-11-24T17:41:30.230 に答える
8
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
            }

        }
    });

ただし、複数のフラグメントが表示される場合は注意してください

于 2016-10-13T13:47:59.540 に答える
4

私はあなたと非常によく似たコードを持っています.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();
    }

 }
于 2017-05-19T20:45:14.860 に答える
1

私にとっては、navGraph を使用してフラグメントを切り替えることが原因でした

app:navGraph

このようなフラグメントを(Kotlinで)作成すると、すべてのライフサイクル関数が呼び出されます

val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.nav_host_fragment, fragment)
transaction.addToBackStack(null)
transaction.commit()
于 2021-06-01T14:39:37.320 に答える
1

あなたはこれを試すことができます、

Step1: アクティビティで 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();
}
于 2016-01-20T12:25:31.900 に答える
1

onPause()メソッドは、使用できるアクティビティ クラスで機能します。

public void onDestroyView(){
super.onDestroyView    
}

同じ目的で..

于 2017-04-02T13:44:28.733 に答える
0

フラグメントにフラグメントを追加することはできません。これは FragmentActivity で発生する必要があります。FragmentActivity で LoginFragment を作成していると想定しているため、これを機能させるには、ログインが終了したときに FragmentActivity を介して HomeFragment を追加する必要があります。

一般的なポイントは、各 Fragment を FragmentManager に追加する場所から FragmentActivity クラスが必要だということです。Fragment クラス内でこれを行うことはできません。

于 2012-11-07T20:53:05.697 に答える
0

フラグメントが表示/非表示になったときに呼び出されることが保証されているオーバーライド メソッドが 2 つあります。

oncreateview/ondestroyview - フラグメントの可視性が変更されるたびに呼び出されます

onpause/onresume - アプリが外部によって閉じられたとき、またはフラグメント置換を使用したときに呼び出されます

私が行ったようにフックを作成したい場合は、フラグメントが閉じられるたびに通知することで、両方が呼び出される可能性があるため、重複した呼び出しを作成せずにいずれかの状況をキャッチできます。

フラグメント クラスを拡張してみて、両方のオーバーライドにブール値フラグを追加して、重複せずにオープンとクローズを確実にキャッチできるようにします。

于 2021-10-26T02:10:20.857 に答える
0

以下の手順に従ってください。必要な回答が得られます。

1- 両方のフラグメントに対して、新しい抽象親フラグメントを作成します。
2-両方で実装する必要があるカスタム抽象メソッドを追加します。
3- 2 番目のインスタンスに置き換える前に、現在のインスタンスから呼び出します。

于 2018-04-09T21:09:33.310 に答える
0

フラグメントは常にアクティビティに埋め込む必要があり、フラグメントのライフサイクルはホスト アクティビティのライフサイクルの影響を直接受けます。たとえば、アクティビティが一時停止されると、その中のすべてのフラグメントも一時停止され、アクティビティが破棄されると、すべてのフラグメントも破棄されます

于 2014-07-16T11:23:16.260 に答える
-3

フラグメントトランザクションを作成するときは、必ず次のコードを追加してください。

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

また、バックスタックに追加した後にトランザクションをコミットすることを確認してください

于 2013-03-07T13:25:17.450 に答える