6

Aby skupić się na problemie, uprość sprawę do następnej - Mam działanie A i fragment F, który dodaje kolejny fragment Dziecko. Uproszczony kod każdy jestWyjątek podczas próby zapisania stanu zagnieżdżonego fragmentu [Fragment już nie istnieje dla klucza android: target_state]

aktywność na

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    // do some stuff 
    FragmentManager fm = getSupportFragmentManager(); 
    F f = new F(); 
    fm.beginTransaction() 
      .add(R.id.content, f) 
      .commit(); 
} 

fragment F

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    // do some stuff 
    FragmentManager fm = getChildFragmentManager(); 
    FragmentTransaction transaction = fm.beginTransaction(); 
    ChildFragment childFragment = new ChildFragment(); 
    childFragment.setTargetFragment(this, 1); 
    transaction.add(R.id.f, childFragment); 
    transaction.commit(); 

    return view; 
} 

Kod fragmentu dziecko nie ma znaczenia dla tego problemu, tak, że po to przyzwyczajenie.

Użycie tego kodu wszystko wydawało się działać poprawnie, dopóki nie zintegrowane Firebase i zacząć Niniejszy raport katastrofie

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.test/com.test.test.A}: java.lang.IllegalStateException: Fragment no longer exists for key android:target_state: index 1 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429) 
    at android.app.ActivityThread.access$800(ActivityThread.java:151) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342) 
    at android.os.Handler.dispatchMessage(Handler.java:110) 
    at android.os.Looper.loop(Looper.java:193) 
    at android.app.ActivityThread.main(ActivityThread.java:5341) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:515) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641) 
    at dalvik.system.NativeStart.main(Native Method) 

Na początku nie mogłem odtworzyć wyjątek, ale po przetestowaniu przez chwilę znalazłem, że jeśli Opcja programisty Nie kontynuuj działań jest na stanie się prawie za każdym razem, gdy wprowadzam aktywność do tła i wznawiam ją. Myślę, że w normalnym przypadku stanie się to, gdy działanie zostanie umieszczone w tle, a aplikacja zostanie zniszczona.

Po przeprowadzeniu badań dochodzę do wniosku, że faktycznym powodem awarii jest to, że fragment F jest ustawiony jako fragment docelowy dla dziecka. Mogę potwierdzić, że jeśli nie ustawię fragmentu docelowego, awarie się nie pojawią.

Nie jestem absolutnie pewny, ale wydaje się, że przyczyną katastrofy jest to, że Fragment Dziecka i jego fragment docelowy znajdują się w różnych FragmentManagerach. Pierwszą rzeczą, którą próbowałem, było umieszczenie wszystkich fragmentów w menedżerze fragmentów aktywności.

fragment F

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    // do some stuff 
    // I do not want to use private fragment manager but rather use the activity's 
    // FragmentManager fm = getChildFragmentManager(); 
    FragmentManager fm = getFragmentManager(); 
    // do the other stuff 
} 

to rozwiązano ten problem. Ale doprowadzić do kolejnego. Po usunięciu fragmentu z działania (chcę go zastąpić innym fragmentem). Fragment potomny nie może zapisać swojego stanu, ponieważ zawiera odniesienie do jego fragmentu macierzystego, który został usunięty z menedżera.

Process: com.test.test, PID: 11047 java.lang.IllegalStateException: Failure saving state: ChildFragment{423c10f0 #1 id=0x7f0b0058} has target not in fragment manager: F{423c0f88} 
    at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:2618) 
    at android.support.v4.app.FragmentController.saveAllState(FragmentController.java:134) 
    at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:571) 
    at android.support.v7.app.AppCompatActivity.onSaveInstanceState(AppCompatActivity.java:515) 
    at android.app.Activity.performSaveInstanceState(Activity.java:1157) 
    at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1229) 

mogę spróbować głębiej i usunąć fragment dziecka, gdy jego rodzic zostaje usunięty, ale mam wrażenie, nie jest to dobry sposób, żeby to zrobić, mimo wszystko uważam, że właściwą drogą do tego jest za pomocą metody getChildFragmentManager().

Każda pomoc, sugestie, wytyczne dotyczące tematu będą bardzo mile widziane.

+0

Dlaczego nie tworzysz i nie dodajesz fragmentów tylko z jednego miejsca - działania A? – helleye

+0

To sprawi, że fragment nie będzie można ponownie użyć. Wszystkie czynności, które dodają fragment, muszą również dodać fragment potomny. –

+0

Czy próbowałeś tego https://code.google.com/p/android/issues/detail?id=54520 – Krish

Odpowiedz

3

Zmieniłem swój kod tak i pracuje dla mnie, Zmień ActivityA tak,

@Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity); 

     FragmentManager fm = getSupportFragmentManager(); 
     if (fm.findFragmentById(R.id.content) == null) { 
      F f = new F(); 
      fm.beginTransaction() 
        .add(R.id.content, f) 
        .commit(); 
     } 
    } 

i można korzystać z poprzednią realizację podobnego setTargetFragment dla fragmentu ChildFragment. To rozwiązało pierwszy wyjątek wspomniany w pytaniu.

+0

@MojoRisin Czy próbowałeś mojej odpowiedzi? – Krish

+0

Wyglądało na to, że szukałem rozwiązania w niewłaściwym miejscu. Jak zauważyłeś, problem polegał na tym, że dodawałem fragment, niezależnie od tego, czy już tam jest. –

Powiązane problemy