110 votes

Obtention de l'erreur "L'activité Java.lang.IllegalStateException a été détruite" lors de l'utilisation d'onglets avec ViewPager

J'ai une application qui se compose de l'aide ActionBarSherlock dans l'onglet mode.J'ai 5 onglets et le contenu de chaque onglet est gérée à l'aide de fragments. Pour tab2 si, j'ai un fragment du fichier xml qui est titulaire d'un ViewPager élément qui à son tour a un certain fragment de pages. Quand j'ai d'abord démarrer l'application l'application, je suis en mesure de basculer entre les onglets, aucun problème, mais lorsque j'appuie sur le tab2 pour la deuxième fois, j'obtiens le message d'erreur mentionné ci-dessus. L'activité principale est la suivante:

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) 
        {

        }
    }
}

Le fragment de la classe sans le ViewPager est comme suit:

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

Le fragment de classe avec le ViewPager est comme suit:

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

De ce que j'ai lu à différents endroits (et s'il vous plaît corrigez-moi si je me trompe), cela se produit parce que le fragment manager sur le deuxième passage, essaie de réutiliser les fragments provenant de l'activité qui n'existe plus donc de donner à l'erreur.Mais je ne suis pas sûr de savoir pourquoi cela se passe par ici car je ne suis pas en utilisant fragment de l'activité. Selon logcat l'erreur est dans le Tab2 classe, onViewCreated méthode sur la ligne qui dit mViewPager.setAdapter(mMyFragmentPagerAdapter). Toute aide est grandement appréciée...Merci.

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)

284voto

Marcus Forsell Stahre Points 2172

Cela semble être un bug dans le support nouvellement ajouté pour les fragments imbriqués. Fondamentalement, l'enfant FragmentManager se retrouve avec un état interne cassé lorsqu'il est détaché de l'activité. Une solution à court terme qui résout ce problème pour moi consiste à ajouter ce qui suit à onDetach() de chaque Fragment que vous appelez getChildFragmentManager() sur:

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

13voto

jekatt Points 71

J'ai exactement le même problème. La seule solution de contournement que j'ai trouvée consiste à remplacer les fragments par une nouvelle instance, chaque fois que les onglets sont modifiés.

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

Pas une vraie solution, mais je n'ai pas trouvé le moyen de réutiliser l'instance de fragment précédente ...

7voto

user1050133 Points 135

J'ai rencontré le même problème lors de l'appel à super.onCreate() à la fin de ma méthode. La raison: attachActivity() est appelée dans onCreate() de FragmentActivity. Lors de la substitution onCreate() et, par exemple, la création d'onglets, l'Onglet gestionnaire va essayer de passer à un fragment tout en n'ayant pas l'activité rattachée à la FragmentManager.

Solution Simple: Déplacer l'appel à super.onCreate() à la tête du corps de la fonction.

En général, il semble que il ya des tas de raisons, ce problème peut se produire. C'est juste une autre ...

Matthias

4voto

sgarman Points 3174

Je voulais ajouter que mon problème était lié à une activité dans laquelle j'ai essayé de créer une transaction de fragment dans onCreate AVANT d'avoir appelé super.onCreate (). Je viens de déplacer super.onCreate () en haut de la fonction et tout fonctionnait bien.

2voto

Malachiasz Points 1537

J'ai eu cette erreur parce que j'utilisais LocalBroadcastManager et j'ai:

 unregisterReceiver(intentReloadFragmentReceiver);
 

au lieu de:

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X