Problem
Na androidzie czasami możemy natrafić na taki błąd:
Can not perform this action after onSaveInstanceState
właściwie dobrze opisuje dlaczego błąd wystąpił. Nie możemy wykonać akcji, którą zamierzaliśmy wykonać po wywołaniu metody onSaveInstanceState
. Błąd ten może się pojawić, gdy dodajemy do widoku fragment, a akurat użytkownik pomyślał, że jednak wyjdzie z aplikacji (przyciskiem home) lub aplikacja została przeniesiona do tła, bo np. ktoś do nas zadzwonił. Jeśli metoda Commit
z FragmentTransaction
zostanie wywołana po onSaveInstanceState
, to dostaniemy powyższy błąd. Problem dokładniej jest opisany w tym poście. Stworzyłem przykładowy projekt, który prezentuje ten problem. Możecie go ściągnąć tutaj:
https://github.com/tomwis/OnSaveInstanceStateExceptionSample
Uruchomcie aplikację w konfiguracji Debug
. Jeśli zaznaczycie switcha i wyjdziecie przyciskiem home, to pojawi się wyjątek – ponieważ dodajemy fragment w OnStop
, które wywołuje się już po onSaveInstanceState
.
Rozwiązanie
Rozwiązanie wydaje się proste – nie commitować fragmentów, gdy aplikacja jest zatrzymana. Jednak zazwyczaj nie robimy tego specjalnie, tylko dzieje się to asynchronicznie i wychodzi tak przez przypadek. Rozwiązaniem może być tutaj przechwytywanie takich fragmentów, wstawianie ich do kolejki i tworzenie ich po powrocie do aplikacji. Robimy to w następujący sposób:
- W miejscu gdzie commitujemy fragment, sprawdzamy przed commitem czy została już wywołana metoda
onSaveInstanceState
. Jeśli nie, to kontynuujemy, a jeśli tak, to zapisujemy fragment do kolejki. - W aktywności dodajemy metodę
override void OnPostResume()
. W niej możemy przejść przez kolejkę zapisanych fragmentów i stworzyć je.
Taka metoda jest również zaimplementowana w przykładzie na githubie zalinkowanym wyżej. Musimy tylko uruchomić aplikację w konfiguracji DebugCorrect
– wtedy będziemy używać aktywności MainActivityWithQueue
. Najważniejsze części: