IllegalArgumentException: Pas de vue pour un identifiant de fragment lors de la commutation rapide des Onglets ActionBar
Je développe une application Android pour les tablettes et pas à l'aide de la bibliothèque de compatibilité.
Il y a juste une Activité et il utilise l'ActionBar avec 3 onglets.
Dans le TabListener-je utiliser setContentView à charge de la mise en page spécifique à cet onglet, puis ajouter les fragments pertinents à leurs cadres.
Cette presque fonctionne exactement comme je le veux, sauf lorsque vous basculez entre les onglets assez vite l'application crash.
J'utilise un Samsung Galaxy Tab comme mon débogage de l'appareil de commutation et d'onglets est vraiment rapide. À un rythme normal, je peux appuyez sur les deux sens entre eux et les pages sont chargées instantanément. Le problème, c'est quand j'ai hyper basculer entre les onglets.
Au début, j'ai eu un
IllegalStateException: Fragment not added
comme on le voit ici:
http://code.google.com/p/android/issues/detail?id=17029
Suite à la suggestion d'utiliser les blocs try/catch dans onTabUnselected, j'ai fait de l'application un peu plus solide, mais qui conduisent à la question à portée de main:
IllegalArgumentException: No view found for id 0x... for fragment ...
Je n'ai pas trouvé d'autres cas sur le web de toute autre personne ayant le même problème, donc je suis inquiet que je peut être en train de faire quelque chose qui n'est pas pris en charge. Nouveau, ce que j'essaie de faire est d'utiliser 3 mises en page différentes dans une Activité lorsque vous cliquez sur un onglet, l'auditeur appel setContentView pour modifier la mise en page, puis ajouter les fragments. Il fonctionne à merveille, sauf si vous lancez agressive de basculer entre les onglets.
J'ai eu l'idée de ce à partir de: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.html
et au lieu de la TabListener garder une référence à un fragment, j'ai un tableau d'entre eux. Aussi, je ne suis pas en utilisant attacher/détacher depuis ceux qui ont été simplement ajouté à l'API 13.
Ma théorie est que ce soit setContentView n'a pas fini de créer les points de vue, et c'est pourquoi FragmentTransaction ne pouvez pas les ajouter, OU les fragments sont ajoutés à un onglet quand un autre onglet est sélectionné et setContentView est appelé, en détruisant l'autre ensemble de points de vue.
J'ai essayé de pirater quelque chose pour ralentir l'onglet de commutation, mais ne pas obtenir n'importe où.
Voici le code de mon TabListener:
private class BTabListener<T extends Fragment> implements ActionBar.TabListener{
private int mLayout;
private Fragment[] mFrags;
private TabData mTabData;
private Activity mAct;
private boolean mNoNewFrags;
public BTabListener(Activity act, int layout, TabData td, boolean frags){
mLayout = layout;
mTabData = td;
mAct = act;
mNoNewFrags = frags;
mFrags = new Fragment[mTabData.fragTags.length];
for(int i=0; i<mFrags.length; i++){
//on an orientation change, this will find the fragments that were recreated by the system
mFrags[i] = mAct.getFragmentManager().findFragmentByTag(mTabData.fragTags[i]);
}
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
//this gets called _after_ unselected
//note: unselected wont have been called after an orientation change!
//we also need to watch out because tab 0 always gets selected when adding the tabs
//set the view for this tab
mAct.setContentView(mLayout);
for(int i=0; i<mFrags.length; i++){
//this will be null when the tab is first selected
if(mFrags[i]==null ){
mFrags[i] = Fragment.instantiate(GUITablet.this, mTabData.classes[i].getName());
}
//if there was an orientation change when we were on this page, the fragment is already added
if(!mNoNewFrags || mDefaultTab!=tab.getPosition()){
ft.add(mTabData.containterIDs[i], mFrags[i], mTabData.fragTags[i]);
}
}
mNoNewFrags = false;
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
//this gets called when another tab is selected, before it's onSelected method
for(Fragment f : mFrags){
try{ //extra safety measure
ft.remove(f);
}catch(Exception e){
e.printStackTrace();
System.out.println("unselect couldnt remove");
}
}
}
}
Et enfin, la trace de la pile:
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): java.lang.IllegalArgumentException: No view found for id 0x7f0b0078 for fragment Fraggle{40ab2230 #2 id=0x7f0b0078 dummy2}
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:729)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:926)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at android.app.BackStackRecord.run(BackStackRecord.java:578)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1226)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at android.app.FragmentManagerImpl$1.run(FragmentManager.java:374)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at android.os.Handler.handleCallback(Handler.java:587)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at android.os.Handler.dispatchMessage(Handler.java:92)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at android.os.Looper.loop(Looper.java:132)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at android.app.ActivityThread.main(ActivityThread.java:4028)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at java.lang.reflect.Method.invokeNative(Native Method)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at java.lang.reflect.Method.invoke(Method.java:491)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
09-29 01:53:08.200: ERROR/AndroidRuntime(4611): at dalvik.system.NativeStart.main(Native Method)
MERCI!!!!!
avez-vous essayé le corrigé...?
OriginalL'auteur hooby3dfx | 2011-09-28
Vous devez vous connecter pour publier un commentaire.
Ok, trouvé un moyen de contourner cela:
Mettre les références à des fragments dans les fichiers de mise en page, et entouré le setContentView appel dans onTabSelected dans un bloc try/catch.
La gestion des exceptions a pris soin d'elle!
Pourquoi je me retrouve avec un écran vide? Je pense que les erreurs ne s'est passé lors de la commutation rapide soit non choisis ou sélectionnés au COURS d'un autre select, donc la dernière sélectionnez serait pour toujours, sans aucune exception).
OriginalL'auteur hooby3dfx
Je sais que c'est un peu une vieille question, mais j'ai eu la même et de trouver un autre travail.
La méthode elle-même est décrite ici Éviter de les recréer point de vue même lorsque vous effectuez onglet de commutation
mais sur le contexte de ce crash, faire Afficher/Masquer au lieu d'ajouter/remplacer évite de plusieurs rapide des appels à onCreateView sur le fragment.
Mon code final est terminé quelque chose comme ceci:
OriginalL'auteur Budius
De voir un cas similaire dans un Google Play rapport de crash.
Code:
^^ C'est là que ça se bloque
Le fragment est bel et bien là (il a été renvoyé par findFragmentById), mais en l'appelant hide() a explosé avec la "IllegalStateException: Fragment pas ajouté"
Pas ajouté? Comment est-il pas si findFragmentById a été capable de le trouver?
Tous FragmentManager appels sont fabriqués à partir le thread d'INTERFACE utilisateur.
Le fragment être enlevé (fragDisplay) a été ajouté plus tôt et je suis sûr que son FragmentTransaction a été commis.
OriginalL'auteur Kostya Vasilyev
Fixe en boucle dans mes fragments, de supprimer un de ceux qui ont été ajoutés, puis l'ajout de la nouvelle. Aussi vérifiez d'abord que vous n'êtes pas d'essayer de le remplacer par la valeur null ou d'un fragment.
Edit: on dirait que c'est juste
qui a cessé de s'écraser
OriginalL'auteur kylarsturn