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


Tengo una aplicación que consiste en usar ActionBarSherlock en modo tab.Tengo 5 pestañas y el contenido de cada pestaña se maneja usando 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 de la aplicación, soy capaz de cambiar entre las pestañas no hay problema, pero cuando presiono en tab2 por segunda vez me sale el error mencionado anteriormente. La actividad principal es como sigue:

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 fragment 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 fragment 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íjame si me equivoco), esto sucede porque el administrador de fragmentos en la segunda pasada intenta reutilizar los fragmentos de la actividad que ya no existe, dando así el error.Pero no estoy seguro de por qué sucede esto aquí ya que no estoy usando actividad de fragmento. De acuerdo con logcat el error está en la clase Tab2, método onViewCreated 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)
Author: Fllo, 2013-03-04

12 answers

Esto parece ser un error en el soporte recién 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 a corto plazo que lo arregló para mí es agregar lo siguiente a onDetach() de cada Fragment que llame 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);
    }
}
 277
Author: Marcus Forsell Stahre,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-27 10:18:14

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 manera de reutilizar la instancia de fragmento anterior...

 13
Author: jekatt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-19 23:53:46

Encontré el mismo problema al llamar a super.onCreate() al final de mi método. La razón: attachActivity() se llama en onCreate() de FragmentActivity. Al sobrescribir onCreate() y, por ejemplo, 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() a la cabeza del cuerpo de la función.

En general, parece que hay muchas razones por las que este problema puede ocurrir. Esto es sólo otro una ...

Matthias

 6
Author: user1050133,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-08 11:31:42

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

 4
Author: sgarman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-08 11:32:20

Tuve este error porque estaba usando LocalBroadcastManager y lo hice:

unregisterReceiver(intentReloadFragmentReceiver);

En lugar de:

LocalBroadcastManager.getInstance(this).unregisterReceiver(intentReloadFragmentReceiver);
 2
Author: Malachiasz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-10 14:47:38

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

 2
Author: Swapnil Chaudhari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-19 06:41:53

Obtuve el mismo error al intentar acceder al hijo FragmentManager antes de que el fragmento se inicializara completamente (es decir, se adjuntara a la Actividad o al menos se llamara onCreateView()). De lo contrario, FragmentManager se inicializa con una actividad null que causa la excepción antes mencionada.

 1
Author: ubuntudroid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-13 06:03:05

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

fragment = null;
 1
Author: MobileMon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-30 17:17:45

Sé que este es un post antiguo, 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();
    }
}
 1
Author: SquareBox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-15 08:05:05

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 de nuevo.

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 ejecuta "finish ()" la actividad llama a " onDestroy ()", pero estoy usando subprocesos y quería asegurarme de que todos los subprocesos se destruyan antes de comenzar la siguiente actividad, y parece que "finish ()" no siempre es inmediato. Necesito procesar / reducir muchos " Mapas de bits "y mostrar grandes" mapas de bits " y estoy trabajando en mejorar el uso de la memoria en mi aplicación

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

public void finishAction() {
  onDestroyThreads();
  finish();
}
 0
Author: user713059,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-03 08:48:33

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

 0
Author: LukasE078,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-16 15:41:38

Este me volvió loco por Xamarin.

Me encontré con esto con una implementación de ViewPager para TabLayout DENTRO de un Fragmento, que a su vez se implementa en DrawerLayout:

 - DrawerLayout
   - DrawerFragment
     - TabLayout
     - TabViewPager
       - TabViewPagerFragments

Así que tienes que implementar el siguiente código en tu DrawerFragment. Tenga en cuenta que debe elegir la ruta de FragmentManager correcta. Porque podrías tener dos FragmentManager diferentes Referencias:

  1. Androide.Apoyo.V4.App.FragmentManager
  2. Androide.App.FragmentManager

Choose> Elija el que utilice. Si desea hacer uso del ChildFragmentManager, tuvo que usar la declaración de clase Android.App.FragmentManager para tu ViewPager!

Androide.Apoyo.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+"");
    }
}

Androide.App.FragmentManager

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

Eso significa que tuvo que iniciar el 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+"");
    }
}
 0
Author: Lepidopteron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-26 08:11:13