93 votes

FragmentManager exécute déjà des transactions. Quand est-il prudent d'initialiser le pager après le commit?

J'ai une activité d'hébergement de deux fragments. L'activité commence en montrant un chargeur pendant qu'il se charge d'un objet. Le chargé de l'objet est ensuite transmis à la fois des fragments comme arguments par newInstance méthodes et ces fragments sont attachés.

final FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
trans.replace(R.id.container1, Fragment1.newInstance(loadedObject));
trans.replace(R.id.container2, Fragment2.newInstance(loadedObject));
trans.commit();

Le deuxième fragment contient un android.de soutien.v4.vue.ViewPager et les onglets. onResume nous l'initialiser comme suit

viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(adapter.getCount()); //the count is always < 4
tabLayout.setupWithViewPager(viewPager);

Le problème est android puis la jette

java.lang.IllegalStateException: FragmentManager est déjà en cours d'exécution les transactions

Avec cette trace de la pile: (j'ai repris android.support du paquet de noms juste pour des raisons de concision)

v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1620) au v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:637) au v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:143) au v4.vue.ViewPager.remplir(ViewPager.java:1235) au v4.vue.ViewPager.remplir(ViewPager.java:1083) au v4.vue.ViewPager.setOffscreenPageLimit(ViewPager.java:847)

Les données montrent si setOffscreenPageLimit(...); est supprimé. Est-il une autre façon d'éviter ce problème?

Quand dans le cycle de vie est le fragment de la transaction complète, de sorte que je peux attendre pour l'installation de mon téléavertisseur?

230voto

Hitesh Sahu Points 12561

Utilisez simplement childFragmentManger() pour viewpager dans un Fragment

 mPagerAdapter = new ScreenSlidePagerAdapter(getChildFragmentManager());
mPager.setAdapter(mPagerAdapter);
 

71voto

M.Paunov Points 482

J'ai eu cette exception lorsque les remplacer rapidement 2 fragments ET à l'aide de executePendingTransactions(). Sans l'appel de cette il n'y a pas d'exception.

Ce qui était mon cas? J'ai ouvert un fragment et dans ses onResume() (sous condition) je demande à l'activité de remplacer le fragment avec le fragment B. À ce point de l'exception se produit.

Ma solution a été d'utiliser un Gestionnaire.de poste(runnable) qui met à la requête sur l'extrémité du fil de la file d'attente au lieu de courir immédiatement. De cette façon, nous nous assurons que la nouvelle transaction sera exécutée après toutes les opérations précédentes sont terminées.

Donc ma solution était aussi simple que:

Handler uiHandler = new Handler();
uiHandler.post(new Runnable()
{
    @Override
    public void run()
    {
        openFragmentB(position);
    }
});

28voto

marmor Points 4559

Si vous ciblez le SDK 24 ou supérieur, vous pouvez utiliser:

 FragmentTransaction.commitNow()
 

au lieu de commit()

Si vous ciblez d'anciennes versions, essayez d'appeler:

 FragmentManager.executePendingTransactions()
 

après l'appel à commit()

1voto

Mike Hardy Points 3

Si quelqu'un est à l'aide de Robolectric >3.6, et au moins jusqu'4.0.2 avec un ViewPager vous pouvez voir cela, même avec le code correct.

Il y a des informations connexes dans cette github question de suivi le problème pour Robolectric.

Le problème n'est pas résolu alors que j'écris cette réponse, et la seule solutions de contournement sont connus pour utiliser @Config(sdk={27}) qui semble fonctionner pour certains, mais ne fonctionne pas pour moi, ou de mettre en œuvre un ViewPagerShadow avec une solution de contournement dans votre package de test avec le plutôt long code référencé sur github (je peux l'inclure ici, si c'est mieux, mais cela peut ne pas être suffisamment pertinent comme réponse?) et utiliser @Config(ombres={ShadowViewPager.class})

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