44 votes

IllegalStateException lors du remplacement d'un fragment

C'est petit Android 2.2 application de test en utilisant le Package de Compatibilité. C'est la (fausse, bien sûr) je cherche à remplacer un Fragment lors de la réception d'un clic. Je suis en train de le remplacer par un nouveau (et différent) instance de la même Fragment de la classe. Comme je vais l'expliquer, il ne fonctionne pas comme prévu et j'ai besoin d'aide:

public class MainFragmentActivity extends FragmentActivity {
  ...

  public void myAction(View view) {
    ...
    RightFragment newRightFrag = RightFragment.newInstance(myNewOption);
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
    ft.replace(R.id.landscape_right_fragment, newRightFrag);
    ft.commit();
  }
}

Vous aurez sûrement vu ce que mon erreur est. De toute façon, nous allons donner un peu plus d'explication sur ce que l'application doit faire :

Orientation Paysage :

---------                ----------
| L | R |  -> click ->   | L | R2 |
---------                ----------

Sur l'orientation paysage, l'activité a vue avec 2 fragments: "leftLand" & "rightLand", et si vous cliquez sur un bouton du fragment "leftLand" elle change alors crée un nouveau Fragment et le remplace par le "rightLand" Fragment d'instance avec une autre instance de la même FragamentActivity classe. Ce qui les rend différents de ces deux instances est un paramètre passé à "newInstance(int)", il est basé sur l'cliqué sur le bouton.

Orientation Portrait :

-----                  -----
|   |                  |   |
| L |   -> click ->    | R |
|   |                  |   |
-----                  -----

En orientation portrait, il montre juste le fragment "leftPort" (a la même disposition que "leftLand") et si vous cliquez sur son bouton puis il lance une Intention un commence la RightFragmentActivity, ce qui montre le Fragment "rightLand"

Il fonctionne très bien ... si je ne remplace pas le droit de fragment. Si je le fais (en cliquant sur le bouton en orientation paysage), puis ultérieurement sur un changement d'orientation (redémarrage de l'activité) le FragmentActivity n'a pas pu démarrer en raison d'un "IllegalStateException: Fragment RightFragment did not create a view" comme ceci :

D/AndroidRuntime( 1428): Shutting down VM
W/dalvikvm( 1428): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
E/AndroidRuntime( 1428): FATAL EXCEPTION: main
E/AndroidRuntime( 1428): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.agm.test/com.agm.test.MainFragmentActivity}: android.view.InflateException: Binary XML file line #13: Error inflating class fragment
E/AndroidRuntime( 1428):        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
E/AndroidRuntime( 1428):        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
E/AndroidRuntime( 1428):        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3815)
E/AndroidRuntime( 1428):        at android.app.ActivityThread.access$2400(ActivityThread.java:125)
E/AndroidRuntime( 1428):        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2037)
E/AndroidRuntime( 1428):        at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 1428):        at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 1428):        at android.app.ActivityThread.main(ActivityThread.java:4627)
E/AndroidRuntime( 1428):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 1428):        at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime( 1428):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
E/AndroidRuntime( 1428):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
E/AndroidRuntime( 1428):        at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 1428): Caused by: android.view.InflateException: Binary XML file line #13: Error inflating class fragment
E/AndroidRuntime( 1428):        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:582)
E/AndroidRuntime( 1428):        at android.view.LayoutInflater.rInflate(LayoutInflater.java:618)
E/AndroidRuntime( 1428):        at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
E/AndroidRuntime( 1428):        at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
E/AndroidRuntime( 1428):        at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
E/AndroidRuntime( 1428):        at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:198)
E/AndroidRuntime( 1428):        at android.app.Activity.setContentView(Activity.java:1647)
E/AndroidRuntime( 1428):        at com.agm.test.MainFragmentActivity.onCreate(MainFragmentActivity.java:25)
E/AndroidRuntime( 1428):        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
E/AndroidRuntime( 1428):        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
E/AndroidRuntime( 1428):        ... 12 more
E/AndroidRuntime( 1428): Caused by: java.lang.IllegalStateException: Fragment com.agm.test.RightFragment did not create a view.
E/AndroidRuntime( 1428):        at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:287)
E/AndroidRuntime( 1428):        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:558)
E/AndroidRuntime( 1428):        ... 21 more
W/ActivityManager(   59):   Force finishing activity com.agm.test/.MainFragmentActivity

J'ai compris que la vieille "RightFragment" n'est pas détruit après avoir été remplacé. C'est probablement une conséquence de ma mauvaise façon d'essayer de la remplacer.

Toute aide serait vraiment appréciée.

Merci à l'avance!

/ Ange Galindo Muñoz

94voto

theisenp Points 4190

Je pense que vous avez peut-être mal compris mon commentaire, donc je vais vous proposer une explication plus détaillée ici.

Un problème qui se pose couramment avec d'enlever ou de remplacer les fragments, c'est d'essayer de retirer un fragment qui a été ajouté à la mise en page XML au lieu de par programmation en Java. Ce n'est pas le même que le gonflage du fragment de la propre mise en page en onCreateView() fonction du fragment de code Java (c'est ce que vous semblez décrire dans votre réponse à mon commentaire). Pour illustrer ce dont je parle, je vais vous montrer deux façons que les gens essaient de supprimer/remplacer les fragments.

C'est la Mauvaise Façon de le faire:

XML Mise en page:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <fragment android:name="com.example.ExampleFragment"
    android:id="@+id/example_fragment"
    android:layout_weight="1"
    android:layout_width="0dp"
    android:layout_height="match_parent" />

</LinearLayout>

Java:

swapFragment()
{
    Fragment newFragment = new ExampleFragment();
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.replace(R.id.fragment_container, newFragment);
    transaction.addToBackStack(null);
    transaction.commit();
}

Ce code, de ne pas exécuter dans la façon dont vous vous attendez. Le fragment initial qui est ajouté dans le fichier XML de mise en page ne sera pas supprimé. C'est parce que le XML dispositions visent à décrire statique éléments de mise en page. Vous pouvez modifier leur contenu au moment de l'exécution, ou de les cacher, mais vous ne pouvez pas supprimer ces choses de la mise en page. C'est ce que Dianne Hackborn a été dit dans le fil de discussion je l'ai lié à l'avant.

C'est la bonne façon de le faire (Au moins dans mon expérience):

XML Mise en page:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

    <!-- Fragment will go here eventually, but it's not added in the layout -->

</LinearLayout>

Java:

protected void onCreate(Bundle savedInstanceState)
{
     super.onCreate(savedInstanceState);
     setContentView(R.layout.my_layout);

     ExampleFragment newFragment = new ExampleFragment();
     FragmentTransaction transaction = getFragmentManager().beginTransaction();
     transaction.add(R.id.fragment_container, newFragment);
     transaction.commit();
}

...

swapFragment()
{
    Fragment newFragment = new ExampleFragment();
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    transaction.replace(R.id.fragment_container, newFragment);
    transaction.addToBackStack(null);
    transaction.commit();
}

Cette stratégie de ne pas ajouter le fragment dans la mise en page initiale. Au lieu de cela il l'ajoute dans le code Java lorsque l'Activité est créée. Cela lui permet d'être retiré de la mise en page (soit à l'aide d' remove() ou replace())

Cela pourrait ne pas résoudre votre problème, mais c'est une commune de la difficulté que les Fragments de créer. Vous pouvez assurez-vous que vous ajoutez les Fragments de la bonne façon à leur permettre d'être enlevé, puis, si cela ne résout pas le problème que nous pouvons résoudre ce problème.

0voto

Il existe un autre moyen, lorsque vous développez des applications pour tablette avec de grands écrans, vous pouvez gonfler différentes dispositions pour chaque orientation d'écran. Il vous suffit de créer les deux dispositions et de les nommer avec portrait ou paysage; l'orientation.

sur l'événement onClick, identifiez simplement l'orientation avec: getResources (). getConfiguration (). orientation

et fais tes affaires

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