48 votes

Android FragmentTransaction commit Quand ?

Je suis en train de créer une application pour tablette. Dans cette application, il y a une activité avec deux fragments. Le premier fragment est un fragment de liste "connu" qui affiche une simple liste de mise en page d'un élément à partir d'une requête de base de données, le second fragment affiche les détails sur l'enregistrement sélectionné (à partir du fragment de liste). Le problème avec le deuxième fragment est que son type dépend des enregistrements montrés dans la liste. Par exemple, si les enregistrements sont des clients, les détails du client sélectionné sont affichés, si ce sont des articles d'inventaire, les détails de l'article sélectionné sont affichés, etc. Afin de communiquer avec le fragment de détails, j'ai créé une interface que chaque classe de fragment de détails met en œuvre. Le fragment liste est "fixé" dans l'activité à partir du layout xml. Le fragment de détail, quant à lui, est créé lors de la création de l'activité, comme ceci :

super.onCreate(savedInstanceState);
setContentView(R.layout.act_hlpfiles_host);

...

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.laydetailsfragment, FragmentsPool.getHelperFileFragment(501), "recordDetails");
fragmentTransaction.commit();

myDetailsFragment = getFragmentManager().findFragmentByTag("recordDetails");

...

myListFragment = (frg_hlpfiles_lstrecords) getFragmentManager().findFragmentById(R.id.frg_lstrecords);

....
}

Le problème avec ce code est que myDetailsFragment est toujours nul. Cela est dû au fait que fragmentTransaction.commit() ne s'exécute pas immédiatement, mais se produit sur le fil d'exécution principal la prochaine fois que ce fil d'exécution est prêt (comme l'indique la documentation Android).

Si je crée le fragment de détail dans onStart() et instancie le fragment de liste dans onCreate, tout fonctionne bien.

La question est donc la suivante : comment puis-je être sûr que fragmentTransaction.commit() a validé la transaction afin que je puisse travailler avec le fragment ajouté ? En outre, existe-t-il un moyen d'attendre que le commit se produise, puis de continuer avec le reste du code ?

106voto

Mark D Points 1759

Essayez d'exécuter fragmentManager.executePendingTransactions() après avoir validé votre transaction mais avant de trouver par balise et voyez si cela fonctionne pour vous.

2 votes

Hé Mark ! Gues quoi ! Ca marche. Maintenant, j'ai une autre question pour toi, peux-tu me dire pourquoi j'ai lu 3 ou 4 fois la documentation de FragmentTransaction pour trouver une solution à ce problème mais que je n'ai jamais regardé les documents de FragmentManager ? :-)

2 votes

Je suis content que ça ait marché. La documentation pourrait être plus cohérente et intuitive...

10voto

Ostap Andrusiv Points 1697

Dans l'API Android 24 FragmentTransaction est synchrone .commitNow() méthode. C'est dans la référence maintenant : [https://developer.Android.com/reference/Android/app/FragmentTransaction.html#commitNow()](https://developer.android.com/reference/android/app/FragmentTransaction.html#commitNow())

Au contraire, .commit() fonctionne de manière asynchrone. Elle planifie simplement un commit de la transaction.

1voto

Sol Sadek Points 11

J'étais confronté à un problème similaire.

Je pense que l'apprentissage clé ici est l'utilisation de commitNow() au lieu de commit() avec getSupportFragmentManager. Cela empêchera le thread principal de s'exécuter jusqu'à ce que le fragment ait été détruit. C'est impératif lorsque l'on construit des interfaces et que l'on utilise une activité partagée. Je devrais savoir que ça m'a laissé perplexe pendant un moment !

Voici un exemple de code : getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.id.fragment_frame)).commitNow() ;

0voto

PJL Points 5865

".... pour que je puisse travailler avec le fragment ajouté. ? En outre, existe-t-il un moyen d'attendre que la validation ait lieu et de puis continuez avec le reste du code ?"

Tout dépend du travail que vous voulez faire. D'après votre question, je vois que la plupart de votre code de travail devrait être dans votre code de fragment de toute façon, par exemple quand un article d'inventaire est sélectionné.

Lors du rappel lorsqu'un élément de la liste de sélection est sélectionné (afin de modifier le fragment de détails), vous serez en mesure d'obtenir le fragment de détails assez facilement de toute façon.

En outre, vous avez déjà le fragment du retour de FragmentsPool.getHelperFileFragment(501), donc je ne vois pas pourquoi vous avez besoin d'obtenir le fragment via sa balise.

Je suis intéressé de savoir quel travail vous devez faire dans onCreate avec votre fragment de détails ajoutés.

0 votes

Tout d'abord, je vous remercie pour votre réponse. En fait, la plupart du travail est effectué dans le code d'activité (nouvel enregistrement, sauvegarde, suppression, etc.). L'approche que vous avez suggérée est tout à fait correcte mais mon application est un peu plus compliquée, la raison pour laquelle je veux le fragment de détails via le tag est que parfois j'ai besoin de connaître le dernier fragment de détails qui a été affiché avant qu'il ne soit remplacé par un nouveau avec FragmentsPool.getHelperFileFragment(<listID>) afin de créer le backstack. Dans onCreate je ne fais qu'initialiser le premier "look" de l'activité basé sur une ListID. Le code dans ma question est simplifié et non complet.

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