causando un java.Error IllegalStateException, Sin actividad, solo al navegar a Fragment por SEGUNDA vez


Estoy recibiendo un error muy desconcertante que no tengo ni idea de cómo empezar a trabajar a través.

Tengo una aplicación simple con una actividad, las vistas se implementan con Fragmentos. Uno de los fragmentos tiene un ViewPager dentro; así que decidí que quería usar la clase getChildFragmentManager de la biblioteca de soporte v4. También tuve que usar ActionBarSherlock, lo que causó un problema, porque no se envía con la v11 de la biblioteca v4.

Arreglé esto reemplazando la biblioteca de soporte v4 en ABS con la biblioteca v11, y todo compilado y parecía estar funcionando, incluido el ViewPager.

Aquí está la parte extraña:

La primera vez que se abre el fragmento con ViewPager, funciona correctamente; pero la SEGUNDA vez que se navega, la aplicación se bloquea, dando un seguimiento de pila inútil. Desde la depuración, descubrí que el problema estaba con el FragmentManager devuelto por getChildFragmentManager; arroja el error No Activity.

¿Alguien tiene alguna idea de lo que podría estar causando esto?

Enviaré el código que creas relevante.

Gracias, David

Author: keyboardsurfer, 2013-02-18

8 answers

Seguí el enlace en jeremyvillalobos respuesta (que fue muy útil) que me llevó a esta solución.

public class CustomFragment extends Fragment {
    private static final Field sChildFragmentManagerField;

    static {
        Field f = null;
        try {
            f = Fragment.class.getDeclaredField("mChildFragmentManager");
            f.setAccessible(true);
        } catch (NoSuchFieldException e) {
            Log.e(LOGTAG, "Error getting mChildFragmentManager field", e);
        }
        sChildFragmentManagerField = f;
    }

    @Override
    public void onDetach() {
        super.onDetach();

        if (sChildFragmentManagerField != null) {
            try {
                sChildFragmentManagerField.set(this, null);
            } catch (Exception e) {
                Log.e(LOGTAG, "Error setting mChildFragmentManager field", e);
            }
        }
    }

    ...
}

Funciona bien para mí, sin la necesidad de reinstanciar el fragmento.

 46
Author: lopisan,
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-05-23 11:54:44

Esto parece ser un error reportado en

Https://code.google.com/p/android/issues/detail?id=42601

La variable

FragmentManagerImpl mChildFragmentManager;

En Fragmento.java no se establece en null al separarse. Así que la próxima vez que se cargue el fragmento, la variable todavía apunta al último padre.

Como se discutió en ese hilo, una solución es reinstanciar el fragmento.

En mi caso, estaba cambiando entre fragmentos en un ActionBar ficha. El fragmento problemático tiene fragmentos anidados y estaba bloqueando la aplicación al regresar al fragmento del cargador de archivos. Así que este es el código de trabajo:

class MainTabsListener implements ActionBar.TabListener {
    public Fragment fragment;
    public int TabPosition;

    public MainTabsListener(Fragment fragment, int tab_position) {
        this.fragment = fragment;
        TabPosition = tab_position;
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        CurrentFragment = fragment;
        CurrentTabSelectedPos = TabPosition;

        /**
         * This is a work-around for Issue 42601
         * https://code.google.com/p/android/issues/detail?id=42601
         * 
         * The method getChildFragmentManager() does not clear up
         * when the Fragment is detached.
         */
        if( fragment instanceof FileLoaderFragment ){
            fragment = reinstatiateFileLoaderFragment();
        }

        ft.replace(R.id.fragment_container, fragment);

    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(fragment);
    }

}
 23
Author: jeremyvillalobos,
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-05-17 06:17:14

Lamentablemente, es un error de soporte v4, todavía hay: (

Cuando elige otro Fragmento a través del Cajón de navegación u otra cosa similar, el fragmento que tiene sub-fragmentos se separa. Así que el FragmentManager de esos sub-fragmentos (getChildFragmentManager ()) ya no existe. mientras esos fragmentos regresaban, se produjo un error. Bomba!

Obviamente, support v4 debería limpiar mChildFragmentManager en onDetach(), pero no lo hizo, por lo que debemos depender de nosotros mismos. tales como los siguientes códigos en el fragmento que tiene sub-fragmentos:

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

Todo estará bien, que tengas un buen día:)

 4
Author: Kevin Liu,
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-06-13 09:51:46

Puede que tu error sea Android.vista.InflateException?

Si es así,debe inflar el fragmento dinámicamente ,no use el diseño XML.

Y, no debe segmentar el fragmento que está definido en XML Layout a Fragment Transaction.

 2
Author: dmnlk,
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-02-18 05:39:03

Tengo el mismo problema.

En una actividad, tengo 3 bouttons para cambiar el fragmento con la transacción.reemplazar(...)

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.layout_tablet_paneau, mLigneMessageFragment);

Uno de estos fragmentos contiene una página de vista con un FragmentPagerAdapter personalizado. Por lo tanto, debo hacer getChildFragmentManager (), a los fragmentos anidados.

El constructor está aquí:

public LignePagerAdapter(Fragment ligneMessageTabletFragment) {
        super(ligneMessageTabletFragment.getChildFragmentManager());
    }

Así que tengo el mismo error: La primera muestra de este fragmento se tuerce, pero cuando muestro otro fragmento y vuelvo a este, obtengo esto excepción:

02-26 11:57:50.798: D/ACRA(776): Wait for Toast + worker ended. Kill Application ? true
02-26 11:57:50.798: E/AndroidRuntime(776): FATAL EXCEPTION: main
02-26 11:57:50.798: E/AndroidRuntime(776): java.lang.IllegalStateException: No activity
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1075)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1070)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1861)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1474)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:931)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:429)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.os.Handler.handleCallback(Handler.java:587)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.os.Handler.dispatchMessage(Handler.java:92)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.os.Looper.loop(Looper.java:132)
02-26 11:57:50.798: E/AndroidRuntime(776):  at android.app.ActivityThread.main(ActivityThread.java:4126)
02-26 11:57:50.798: E/AndroidRuntime(776):  at java.lang.reflect.Method.invokeNative(Native Method)
02-26 11:57:50.798: E/AndroidRuntime(776):  at java.lang.reflect.Method.invoke(Method.java:491)
02-26 11:57:50.798: E/AndroidRuntime(776):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
02-26 11:57:50.798: E/AndroidRuntime(776):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
02-26 11:57:50.798: E/AndroidRuntime(776):  at dalvik.system.NativeStart.main(Native Method)
02-26 11:57:52.818: I/dalvikvm(776): threadid=4: reacting to signal 3
02-26 11:57:52.818: I/dalvikvm(776): Wrote stack traces to '/data/anr/traces.txt'

Así que en lugar de poner la misma instancia de fragmento, puedo volver a crear esto para que solucione el problema, pero no me parece eficiente.

transaction.replace(R.id.layout_tablet_paneau, LigneMessageTabletFragment.newInstance());
 2
Author: Chtiboss,
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-02-26 11:14:18

Refiérase a @ lopisan respuesta:

Utilizo su solución durante mucho tiempo.

PERO me imagino que tengo una mejor manera de hacer esto!

If mChildFragmentManager.mActivity es null, luego establece mChildFragmentManager en null. Cuando el método performActivityCreated.

@Override
void performActivityCreated(Bundle savedInstanceState) {
    if (getFragmentManagerActivity(mChildFragmentManager) == null) {
        setChildFragmentManager(this, null);
    }
    super.performActivityCreated(savedInstanceState);
}


public static FragmentActivity getFragmentManagerActivity(FragmentManager fragmentManager) {
    FragmentManagerImpl fm = (FragmentManagerImpl) fragmentManager;
    return fm.mActivity;
}



private static final Field sChildFragmentManagerField;
static {
    /**
     * BUG : causing a java.IllegalStateException error, No Activity, only
     * when navigating to Fragment for the SECOND time
     * http://stackoverflow.com /questions/15207305/getting-the-error-java-lang-illegalstateexception-activity-has-been-destroyed
     * http://stackoverflow.com/questions/14929907/causing-a-java-illegalstateexception-error-no-activity-only-when-navigating-to
     */
    Field f = null;
    try {
        f = Fragment.class.getDeclaredField("mChildFragmentManager");
        f.setAccessible(true);
    } catch (NoSuchFieldException e) {
        Log.e(TAG, "Error getting mChildFragmentManager field", e);
    }
    sChildFragmentManagerField = f;
}

public static void setChildFragmentManager(Fragment fragment, FragmentManager fragmentManager) {
    if (sChildFragmentManagerField != null) {
        try {
            sChildFragmentManagerField.set(fragment, fragmentManager);
        } catch (Exception e) {
            Log.e(TAG, "Error setting mChildFragmentManager field", e);
        }
    }
}
 0
Author: 林奕忠,
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-09-09 12:50:52

Estoy atascado con el mismo error usando el interruptor BottomNavigationView y el reemplazo del fragmento que causa el bloqueo de la aplicación. Con la velocidad normal que estaba funcionando perfectamente bien, si el usuario hacer interruptor rápido que solía fallar diciendo

Ilegalstateexception No Activity

En Los Registros

Antes de tener

fragmentA = new FragmentA();
fragmentB = new FragmentB();
fragmentC = new FragmentC();

mBottomNavigationView.setOnNavigationItemSelectedListener(item -> {
        switch (item.getItemId()) {
   case R.id.fragmentA:
         replaceFragment(fragmentA);
   case R.id.fragmentB:
        repalceFragment(fragmentB);
   case R.id.fragmentC:
        repalceFragment(fragmentC);
   }
};

Creo que esta pre-creación de fragmento y el uso de ellos fue para reemplazar está creando el problema, ahora lo hice para volver a crear cada vez. Empezó a funcionar bien

mBottomNavigationView.setOnNavigationItemSelectedListener(item -> {
        switch (item.getItemId()) {
   case R.id.fragmentA:
        fragment = new FragmentA();
         replaceFragment(fragment);
   case R.id.fragmentB:
        fragment = new FragmentB();
        repalceFragment(fragment);
   case R.id.fragmentC:
        fragment = new FragmentC();
        repalceFragment(fragment);
   }
};

 public void repalceFragment(Fragment fragment) {
    if (!this.isFinishing()) {
        if (!fragment.isAdded()) {
            if (!this.mDisplayedFragment.isRemoving()) {
                getFragmentManager().beginTransaction().replace(R.id.layout_fragment_container, fragment).commit();
                this.mDisplayedFragment = fragment;
            }
        }
    }
}

Espero que sea útil para algunos, hice demasiado de codificación defensiva, pero resolvió mi problema de cambio rápido de fragmentos

 0
Author: Sandeep Tengale,
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-07-05 06:52:31

Por favor, compruebe el número 32 de este enlace:

FragmentManager hijo retenido después de separar el fragmento padre

Pasos:

  1. Descargue y copie esta clase en su proyecto
  2. extienda cada fragmento con el soporte v4 one(best practice)
  3. use esa clase en lugar de FragmentStatePagerAdapter
 -1
Author: TharakaNirmana,
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-12-15 11:29:00