vida una studio onstop onrestart manejo crear como ciclo activity actividad android android-fragments onresume back-stack

android - una - Fragmento onResume() y onPause() no se llama en backstack



onresume fragment android (14)

Al crear una transacción de fragmento, asegúrese de agregar el siguiente código.

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

También asegúrese de confirmar la transacción después de agregarla a backstack

Tengo múltiples fragmentos dentro de una actividad. En un botón, haga clic en Comenzaré un nuevo fragmento y lo agregaré al backstack. Naturalmente, esperaba que se onPause() método onPause() del Fragmento actual y onResume() del nuevo Fragmento. Bueno, no está sucediendo.

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

Lo que esperaba, fue,

  1. Cuando se hace clic en el botón, LoginFragment se reemplaza con HomeFragment , onPause() de LoginFragment y onResume() de HomeFragment se llama
  2. Cuando se presiona atrás, HomeFragment aparece y se ve LoginFragment , y se onPause() de HomeFragment y onResume() de LoginFragment .

Lo que obtengo es,

  1. Cuando se hace clic en el botón, HomeFragment reemplaza correctamente a LoginFragment , onResume () de HomeFragment se llama, pero onPause () de LoginFragment nunca se llama.
  2. Cuando se presiona de nuevo, HomeFragment aparece correctamente para revelar LoginFragment , se llama a onPause () de HomeFragment , pero onResume () de LoginFragment nunca se llama.

¿Es este el comportamiento normal? ¿Por qué onResume() de LoginFragment no se llama cuando presiono el botón Atrás?


Aquí está mi versión más robusta de la respuesta de Gor (el uso de fragments.size () no es confiable debido a que el tamaño no se disminuye después de que se hace saltar el fragmento)

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

Y el método ''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; }


Lo que hago en fragmento de niño:

@Override public void onDetach() { super.onDetach(); ParentFragment pf = (ParentFragment) this.getParentFragment(); pf.onResume(); }

Y luego anular onResume en ParentFragment



Puedes probar esto,

Paso 1: anule el método Tabselected en su actividad

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

Paso 2: usando el método estático, haz lo que quieras en tu fragmento,

public static void fragmentChanged() { Toast.makeText(actvity, "Fragment Changed", Toast.LENGTH_SHORT).show(); }


Si agrega el fragmento en XML, no puede intercambiarlos dinámicamente. Lo que ocurre es que son demasiado, por lo que los eventos no se disparan como uno esperaría. El problema está documentado en esta pregunta. FragmenManager replace hace overlay

Convierta middle_fragment en FrameLayout y cárguelo de la siguiente manera y sus eventos se activarán.

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


Si realmente quieres reemplazar el fragmento dentro de otro fragmento, debes usar Fragmentos anidados .

En tu código debes reemplazar

final FragmentManager mFragmentmanager = getFragmentManager();

con

final FragmentManager mFragmentmanager = getChildFragmentManager();


Siempre se debe incrustar un fragmento en una actividad y el ciclo de vida del fragmento se ve directamente afectado por el ciclo de vida de la actividad del host. Por ejemplo, cuando la actividad está en pausa, también lo son todos los fragmentos, y cuando se destruye la actividad, también lo hacen todos los fragmentos


Tengo un código muy similar al suyo y si funciona onPause () y onResume (). Al cambiar el fragmento, estas funciones se activan respectivamente.

Código en fragmento:

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

Registro cuando cambio de fragmento:

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

Fragmento 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; }

Acción cuando pulso hacia atrás (en la actividad donde cargo el fragmento):

@Override public void onBackPressed() { int count = getFragmentManager().getBackStackEntryCount(); if (count == 0) { super.onBackPressed(); } else { getFragmentManager().popBackStack(); } }


Usted simple no puede agregar un fragmento a un fragmento. Esto debe suceder en FragmentActivity. Supongo que está creando LoginFragment en una FragmentActivity, por lo que para que esto funcione debe agregar el HomeFragment a través de FragmentActivity cuando se cierra el inicio de sesión.

El punto general es que necesita una clase FragmentActivity desde donde agrega cada Fragment al FragmentManager. No es posible hacer esto dentro de una clase Fragment.


onPause() método onPause() funciona en clase de actividad que puede usar:

public void onDestroyView(){ super.onDestroyView }

para el mismo propósito ...


Siga los pasos a continuación y obtendrá la respuesta necesaria

1- Para ambos fragmentos, cree un nuevo padre primario abstracto.
2- Agregue un método abstracto personalizado que ambos deberían implementar.
3- Llamar desde la instancia actual antes de reemplazar con la segunda.


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

pero ten cuidado si hay más de un fragmento visible


  • Como ha utilizado ft2.replace() , se llama al método FragmentTransaction.remove() y se Loginfragment el Loginfragment . Consulte this . Entonces se onStop() de LoginFragment lugar de onPause() . (Como el nuevo fragmento reemplaza completamente al anterior).
  • Pero como también ha utilizado ft2.addtobackstack() , el estado del Loginfragment de Loginfragment de Loginfragment se guardará como un paquete y cuando haga clic en el botón HomeFragment de HomeFragment , se onViewStateRestored() seguido de onStart() de LoginFragment . Por lo tanto, eventualmente onResume() no se llamará.