android android-fragments android-viewpager actionbarsherlock android-nested-fragment

android - Obteniendo el error "La actividad Java.lang.IllegalStateException ha sido destruida" al usar pestaƱas con ViewPager



android-fragments android-viewpager (12)

Este me volvió loco por Xamarin.

Me encontré con esto con una implementación de ViewPager para TabLayout DENTRO de un Fragmento, que está implementado en el DrawerLayout:

- DrawerLayout - DrawerFragment - TabLayout - TabViewPager - TabViewPagerFragments

Entonces debes implementar el siguiente código en tu DrawerFragment . Tenga en cuenta que elija el FragmentManager-Path correcto. Porque es posible que tenga dos referencias diferentes de FragmentManager:

  1. Android.Support.V4.App.FragmentManager
  2. Android.App.FragmentManager

-> Elija el que use. Si desea utilizar ChildFragmentManager, debe usar la declaración de clase Android.App.FragmentManager para su ViewPager.

Android.Support.V4.App.FragmentManager

Implemente el siguiente Método en su Fragmento "Principal" - en este ejemplo: DrawerFragment

public override void OnDetach() { base.OnDetach(); try { Fragment x = this; var classRefProp = typeof(Fragment).GetProperty("class_ref", BindingFlags.NonPublic | BindingFlags.Static); IntPtr classRef = (IntPtr)classRefProp.GetValue(x); var field = JNIEnv.GetFieldID(classRef, "mChildFragmentManager", "Landroid/support/v4/app/FragmentManagerImpl;"); JNIEnv.SetField(base.Handle, field, IntPtr.Zero); } catch (Exception e) { Log.Debug("Error", e+""); } }

Android.App.FragmentManager

public class TabViewPager: Android.Support.V13.App.FragmentPagerAdapter {}

Eso significa que debe iniciar ViewPager con Android.App.FragmentManager.

Implemente el siguiente Método en su Fragmento "Principal" - en este ejemplo: DrawerFragment

public override void OnDetach() { base.OnDetach(); try { Fragment x = this; var classRefProp = typeof(Fragment).GetProperty("class_ref", BindingFlags.NonPublic | BindingFlags.Static); IntPtr classRef = (IntPtr)classRefProp.GetValue(x); var field = JNIEnv.GetFieldID(classRef, "mChildFragmentManager", "Landroid/app/FragmentManagerImpl;"); JNIEnv.SetField(base.Handle, field, IntPtr.Zero); } catch (Exception e) { Log.Debug("Error", e+""); } }

Tengo una aplicación que consiste en usar ActionBarSherlock en modo de pestaña. Tengo 5 pestañas y el contenido de cada pestaña se maneja con fragmentos. Sin embargo, para tab2, tengo un fragmento cuyo archivo xml contiene un elemento ViewPager que a su vez tiene algunas páginas de fragmentos. Cuando inicialmente inicio la aplicación, puedo cambiar entre pestañas sin problema, pero cuando presiono tab2 por segunda vez aparece el error mencionado anteriormente. La actividad principal es la siguiente:

public class MainActivity extends SherlockFragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ActionBar actionBar = getSupportActionBar(); ActionBar.Tab tab1 = actionBar.newTab().setText("Tab1"); ActionBar.Tab tab3 = actionBar.newTab().setText("Tab3"); ActionBar.Tab tab2 = actionBar.newTab().setText("Tab2"); ActionBar.Tab tab4 = actionBar.newTab().setText("Tab4"); ActionBar.Tab tab5 = actionBar.newTab().setText("Tab5"); Fragment fragment1 = new Tab1(); Fragment fragment3 = new Tab3(); Fragment fragment2 = new Tab2(); Fragment fragment5 = new Tab5(); Fragment fragment4 = new Tab4(); tab1.setTabListener(new MyTabListener(fragment1)); tab3.setTabListener(new MyTabListener(fragment3)); tab2.setTabListener(new MyTabListener(fragment2)); tab5.setTabListener(new MyTabListener(fragment5)); tab4.setTabListener(new MyTabListener(fragment4)); actionBar.addTab(tab1); actionBar.addTab(tab2); actionBar.addTab(tab3); actionBar.addTab(tab4); actionBar.addTab(tab5); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); } class MyTabListener implements ActionBar.TabListener { Fragment fragment; public MyTabListener(Fragment fragment) { this.fragment = fragment; } @Override public void onTabSelected(com.actionbarsherlock.app.ActionBar.Tab tab,FragmentTransaction ft) { ft.replace(R.id.fragment_container,fragment); } @Override public void onTabUnselected(com.actionbarsherlock.app.ActionBar.Tab tab,FragmentTransaction ft) { } @Override public void onTabReselected(com.actionbarsherlock.app.ActionBar.Tab tab,FragmentTransaction ft) { } } }

La clase de fragmento sin ViewPager es la siguiente:

public class Tab1 extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { return inflater.inflate(R.layout.activity_tab1, container, false); } }

La clase de fragmento con ViewPager es la siguiente:

public class Tab2 extends Fragment { ViewPager mViewPager; private MyFragmentPagerAdapter mMyFragmentPagerAdapter; private static int NUMBER_OF_PAGES = 5; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { View view = inflater.inflate(R.layout.activity_tab2, container, false); return view; } @Override public void onViewCreated(View view,Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mViewPager = (ViewPager) view.findViewById(R.id.viewpager); mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getChildFragmentManager()); mViewPager.setAdapter(mMyFragmentPagerAdapter); } private static class MyFragmentPagerAdapter extends FragmentPagerAdapter { public MyFragmentPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int index) { return PageFragment.newInstance("My Message " + index); } @Override public int getCount() { return NUMBER_OF_PAGES; } } }

Por lo que he leído en diferentes lugares (y por favor corrígeme si estoy equivocado), esto sucede porque el administrador de fragmentos en el segundo pase intenta reutilizar los fragmentos de la actividad que ya no existe, dando el error. Pero no estoy seguro de por qué sucede esto aquí ya que no estoy usando la actividad de fragmentos. Según logcat, el error está en la clase Tab2, en el método ViewCreated en la línea que dice mViewPager.setAdapter (mMyFragmentPagerAdapter). Cualquier ayuda es muy apreciada, gracias.

03-04 12:01:05.468: E/AndroidRuntime(2474): FATAL EXCEPTION: main 03-04 12:01:05.468: E/AndroidRuntime(2474): java.lang.IllegalStateException: Activity has been destroyed 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1342) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:578) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:139) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.support.v4.view.ViewPager.populate(ViewPager.java:1011) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.support.v4.view.ViewPager.populate(ViewPager.java:880) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:433) 03-04 12:01:05.468: E/AndroidRuntime(2474): at com.example.tabs.Tab2.onViewCreated(Tab2.java:31) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:925) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:429) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.os.Handler.handleCallback(Handler.java:587) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.os.Handler.dispatchMessage(Handler.java:92) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.os.Looper.loop(Looper.java:123) 03-04 12:01:05.468: E/AndroidRuntime(2474): at android.app.ActivityThread.main(ActivityThread.java:3687) 03-04 12:01:05.468: E/AndroidRuntime(2474): at java.lang.reflect.Method.invokeNative(Native Method) 03-04 12:01:05.468: E/AndroidRuntime(2474): at java.lang.reflect.Method.invoke(Method.java:507) 03-04 12:01:05.468: E/AndroidRuntime(2474): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842) 03-04 12:01:05.468: E/AndroidRuntime(2474): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600) 03-04 12:01:05.468: E/AndroidRuntime(2474): at dalvik.system.NativeStart.main(Native Method)


Esto parece ser un error en el soporte recientemente agregado para fragmentos anidados. Básicamente, el niño FragmentManager termina con un estado interno roto cuando se separa de la actividad. Una solución temporal a corto plazo que me lo arregló es agregar lo siguiente a onDetach() de cada Fragment que usted llama getChildFragmentManager() en:

@Override public void onDetach() { super.onDetach(); try { Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager"); childFragmentManager.setAccessible(true); childFragmentManager.set(this, null); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } }


Estoy teniendo exactamente el mismo problema. La única solución que he encontrado, es reemplazar los fragmentos por una nueva instancia, cada vez que se cambian las pestañas.

ft.replace(R.id.fragment_container, Fragment.instantiate(PlayerMainActivity.this, fragment.getClass().getName()));

No es una solución real, pero no he encontrado una forma de reutilizar la instancia de fragmento anterior ...


Forzo el fragmento que contiene el fragmento hijo a NULL en onPause y soluciona mi problema

fragment = null;


Me encontré con el mismo problema al llamar a super.onCreate() al final de mi método. El motivo: se llama a attachActivity () enCreate () de FragmentActivity. Al anular onCreate() y, por ejemplo, al crear pestañas, el administrador de pestañas intentará cambiar a un fragmento sin tener la actividad asociada al FragmentManager.

Solución simple: mueva la llamada a super.onCreate() al encabezado del cuerpo de la función.

En general, parece que hay muchas razones por las que este problema puede ocurrir. Este es solo otro ...

Matthias


Me encontré con el mismo problema y más tarde descubrí que, me he perdido la llamada a super.onCreate( savedInstanceState ); en onCreate() de FragmentActivity.


Obtuve el mismo error al intentar acceder al FragmentManager secundario antes de que el fragmento se haya inicializado por completo (es decir, adjuntado a la actividad o al menos onCreateView() llamado). De lo contrario, el FragmentManager se inicializa con una Actividad null causa la excepción antes mencionada.


Quería agregar que mi problema estaba en una actividad donde intenté hacer una FragmentTransaction en onCreate ANTES de llamar a super.onCreate() . Acabo de mover super.onCreate() a la parte superior de la función y funcionó bien.


Sé que esta es una publicación anterior, pero las respuestas sugeridas no funcionaron por mi parte. Quiero dejar esto aquí por si alguien lo encuentra útil.

Lo que hice fue:

@Override public void onResume() { super.onResume(); // add all fragments FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction(); for(Fragment fragment : fragmentPages){ String tag = fragment.getClass().getSimpleName(); fragmentTransaction.add(R.id.contentPanel, fragment, tag); if(fragmentPages.indexOf(fragment) != currentPosition){ fragmentTransaction.hide(fragment); } else { lastTag = tag; } } fragmentTransaction.commit(); }

Luego en:

@Override public void onPause() { super.onPause(); // remove all attached fragments for(Fragment fragment: fragmentPages){ getChildFragmentManager().beginTransaction().remove(fragment).commit(); } }


Tuve este error porque estaba usando LocalBroadcastManager y lo hice:

unregisterReceiver(intentReloadFragmentReceiver);

en lugar de:

LocalBroadcastManager.getInstance(this).unregisterReceiver(intentReloadFragmentReceiver);


Tuve este problema y me di cuenta de que era porque estaba llamando a setContentView(int id) dos veces en el Activity onCreate


Tuve este problema y no pude encontrar la solución aquí, así que quiero compartir mi solución en caso de que alguien más tenga este problema nuevamente.

Tenía este código:

public void finishAction() { onDestroy(); finish(); }

y resolvió el problema eliminando la línea "onDestroy ();"

public void finishAction() { finish(); }

La razón por la que escribí el código inicial: sé que cuando ejecutas "finish ()" la actividad llama a "onDestroy ()", pero estoy usando threads y quería asegurarme de que todos los hilos se destruyan antes de comenzar la siguiente actividad , y parece que "finish ()" no siempre es inmediato. Necesito procesar / reducir una gran cantidad de "Bitmap" y mostrar grandes "bitmaps" y estoy trabajando para mejorar el uso de la memoria en mi aplicación

Ahora mataré los hilos usando un método diferente y ejecutaré este método desde "onDestroy ();" y cuando creo que necesito matar a todos los hilos.

public void finishAction() { onDestroyThreads(); finish(); }