2012-11-15 34 views
65

czasami pojawia się następujący wyjątek podczas pracy z fragmentami:Android FragmentManager BackStackRecord.run rzuca NullPointerException

FATAL EXCEPTION: main 
java.lang.NullPointerException 
    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:591) 
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1416) 
    at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:420) 
    at android.os.Handler.handleCallback(Handler.java:615) 
    at android.os.Handler.dispatchMessage(Handler.java:92) 
    at android.os.Looper.loop(Looper.java:137) 
    at android.app.ActivityThread.main(ActivityThread.java:4745) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:511) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
    at dalvik.system.NativeStart.main(Native Method) 

Wyjątek występuje wtedy, gdy run() z BackStackRecord jest nazywany przez execPendingTransactions(), gdy próbuje usunąć fragment od kierownika .

case OP_REMOVE: { 
    Fragment f = op.fragment; 
    f.mNextAnim = op.exitAnim; <---- 
    mManager.removeFragment(f, mTransition, mTransitionStyle); 
} 
break; 

Nie mogę się domyślić, co to jest przyczyną? Myślę, że ma to związek z tym, że fragmenty nie są prawidłowo oczyszczane.

Odpowiedz

158

Odpowiadając na moje własne pytanie:

Ten wyjątek jest (w końcu) rzucony podczas rozmowy FragmentTransaction.remove(null); i FragmentTransaction.commit();

EDIT: A także, jak dwa razy w kółku i shinyuX podkreślić w komentarzu; gdy wywołanie show(null) lub add(null), attach(null) i detach(null) metod, a prawdopodobnie również hide(null)

Po wywołaniu commit(), transakcja zostanie umieszczony w kolejce w FragmentManager. W wyniku tego, gdy operacja jest przetwarzana po jawnym wywołaniu FragmentManager.executePendingTransactions() lub gdy wątek kolejki FragmentManager wywoła ją, wyśle ​​ona NullPointerException.

W moim przypadku utrzymywałem stany fragmentów w obiekcie globalnym. Tam sprawdziłem, czy fragment się wyświetlał, a następnie usunąłem widoczne fragmenty. Ale ponieważ zacząłem nowy FragmentActivity, stany te wciąż były prawdziwe, gdy nie były widoczne. Jest to więc błąd projektowy.

Oprócz usunięcia błędu projektowego rozwiązanie było proste: sprawdź, czy przed usunięciem fragmentu zwrócił FragmentManager.findFragmentByTag()null.

+14

Dobra odpowiedź - pomogło mi to rozwiązać mój problem. Jedna rzecz do zapamiętania, otrzymasz ten sam błąd, gdy wywołasz FragmentTransaction.show (null), .hide (null) itp. Nie tylko .remove (null). Mam nadzieję, że pomoże to innym w odnalezieniu problemu. –

+0

Dzięki @NickL ...... – hemu

+1

Pomógł mi DUŻO! Zauważ, że nie powiedzie się z żadną akcją wysłaną z fragmentem zerowym (w moim przypadku 'attach'' detach' – shinyuX

-2

Nie używam znacznika do tworzenia fragmentów (działają one jak kontenery TabBar).

Działa to po zmianie Tab, ale jeśli kliknę przycisk Wstecz, otrzymałem ten sam błąd.

W metodzie onDestroyView znalazłem instancję fragmentu z FragmentManager # findFragmentById, jednak FragmentManager # findFragmentByTag zwraca null, sure.

class MyFragment extends ListFragment { 

@Override 
public void onDestroyView() { 
    super.onDestroyView(); 

    if (this.mapFragment != null 
      && getFragmentManager().findFragmentById(
        this.mapFragment.getId()) != null) { 

     getFragmentManager().beginTransaction().remove(this.mapFragment) 
       .commit(); 
     this.mapFragment = null; 
    } 

} 
} 
+2

Dlaczego konieczne jest ustawienie mapFragment na wartość null? –

+1

Pytanie, na które warto odpowiedzieć: - 'Dlaczego konieczne jest ustawienie parametru mapFragment na wartość null?' – nmxprime

Powiązane problemy