IllegalStateException podczas zastępowania fragmentu

To mała aplikacja testowa Androida 2.2 z wykorzystaniem pakietu kompatybilności. Jest to (oczywiście niewłaściwy) sposób, w jaki próbuję zastąpić Fragment po otrzymaniu kliknięcia. Próbuję zastąpić go nową (inną) instancją tej samej klasy Fragment. Jak wyjaśnię to nie działa zgodnie z oczekiwaniami i potrzebuję pomocy: {]}

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();
  }
}
Na pewno zobaczycie, jaki jest mój błąd. W każdym razie dajmy trochę więcej wyjaśnień na temat tego, co aplikacja powinna zrobić:

Krajobraz Orientacja:

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

W orientacji poziomej ćwiczenie ma widok z 2 fragmentami: "leftLand" & "rightLand", a jeśli klikniesz przycisk fragmentu " leftLand ", to zmienia się tworząc nowy Fragment i zastępuje instancję fragmentu" rightLand " inną instancją tej samej klasy FragamentActivity. To, co odróżnia te dwie instancje, to parametr przekazany do " newInstance (int)", oparty na kliknięciu guzik.

Orientacja Portretowa:

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

W orientacji pionowej po prostu pokazuje fragment " leftport" (ma taki sam układ jak "leftLand") i jeśli klikniesz jego przycisk, uruchamia intencję i uruchamia RightFragmentActivity, który pokazuje Fragment "rightLand "

Działa dobrze ... jeśli nie podmienię WŁAŚCIWEGO fragmentu. Jeśli to zrobię (klikając przycisk w orientacji poziomej) to na następnej orientacji zmiana (restart aktywności) fragment nie może się rozpocząć z powodu "IllegalStateException: Fragment RightFragment did not create a view" Tak:
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

Zdałem sobie sprawę, że stary " RightFragment" nie jest zniszczony po wymianie. Jest to prawdopodobnie konsekwencja mojego niewłaściwego sposobu, aby spróbować go zastąpić.

Każda pomoc będzie naprawdę mile widziana.

Z góry dzięki!

/ Angel Galindo Muñoz

Author: galvan, 2011-10-10

2 answers

Myślę, że może źle zrozumiałeś mój komentarz, więc oferuję bardziej szczegółowe wyjaśnienie tutaj.

Jednym z problemów, który często pojawia się przy usuwaniu lub zastępowaniu fragmentów, jest próba usunięcia fragmentu, który został dodany do układu za pomocą XML, a nie programowo w Javie. Jest to a nie to samo, co nadmuchiwanie własnego układu fragmentu w funkcji onCreateView() kodu Java fragmentu (to chyba opisujesz w odpowiedzi na mój komentarz). Na zilustruj to, o czym mówię, pokażę Ci dwa sposoby, że ludzie próbują usunąć/zastąpić fragmenty.

To jest zły sposób, aby to zrobić:

układ XML:

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

Ten kod nie zostanie wykonany w sposób, jakiego oczekujesz. Początkowy fragment dodany w układzie XML nie zostanie usunięty. Dzieje się tak, ponieważ układy XML są przeznaczone do opisywania statycznych elementów układu. Możesz zmienić ich zawartość podczas uruchamiania czasu, lub ukryć je, ale nie można usunąć tych rzeczy z układu. To właśnie mówiła Dianne Hackborn w wątku dyskusyjnym , do którego wcześniej nawiązałem.

Jest to właściwy sposób (przynajmniej z mojego doświadczenia):

układ XML:

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

Ta strategia nie dodaje fragmentu w początkowym układzie. Zamiast tego dodaje go w kodzie Java podczas tworzenia aktywności. To pozwala na usunięcie go z układu (używając remove() lub replace())

Może to nie rozwiąże Twojego problemu, ale jest to częsta trudność, którą tworzą fragmenty. Możesz upewnić się, że dodajesz fragmenty w odpowiedni sposób, aby umożliwić ich usunięcie, a jeśli to nie rozwiąże problemu, możemy rozwiązać dalej.

 94
Author: theisenp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-10 19:37:25

Jest inny sposób, gdy tworzysz aplikacje na tablet z dużymi ekranami, możesz nadmuchać układ diferentów dla każdej orientacji ekranu.wystarczy utworzyć dwa układy i nazwać je pionowym lub poziomym, w onCreate po prostu nadmuchać xml zgodnie z orientacją.

W zdarzeniu onClick po prostu zidentyfikuj orientację za pomocą: getResources ().getConfiguration ().orientacja

I rób swoje

 0
Author: Juan Pablo Alvarez Ovalle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-19 18:13:39