2015-05-27 20 views
15

W mojej aplikacji przechowuję ważne dane w SharedPreferences - działa tak, jak potrzebuję. Teraz chcę utworzyć komunikaty dziennika dla niektórych nieprawidłowych sytuacji.Kiedy commit Androida SharedPreferences() zwraca wartość false?

Mam wiadomość dla sytuacji, gdy preferencje są puste lub po prostu wyrzucają wyjątek podczas ładowania. Tylko niepoprawna sytuacja podczas zapisywania może pojawić się, jeśli metoda commit() zwróci false - nie wiem, dlaczego tak się stanie i co powinienem zrobić w tym przypadku.

Pytanie brzmi - czy metoda commit() zwraca wartość false? Czy i tak może być rozwiązaniem dla sukcesu?

+0

Zwraca wartość true, jeśli nowe wartości zostały pomyślnie zapisane w pamięci trwałej. Sprawdź: http://developer.android.com/reference/android/content/SharedPreferences.Editor.html#commit() –

+0

i myślę, że zwróci false, gdy plik jest uszkodzony lub problem z I/O .. ale te problemy występują bardzo rzadko ... – Moinkhan

+0

rozważ, czy zmienisz typ danych dla klucza w pewnym momencie. Z pewnością zwróci false. – Randroid

Odpowiedz

10

Po pierwsze, nigdy byś nie chciał: while(!editor.commit()) {;}. Jeśli chcesz ponowić zatwierdzenie, zrobiłbyś to kilka razy, a nie na zawsze.

Odnośnie gdy commit() zwraca -1: Zarówno commit(), jak i apply() wprowadzają zmiany w pamięci, a następnie wykonują wywołania, aby zapisać zmiany na dysku (per source). commit() czeka na powrót zapisu dysku, aby zwrócić wyniki. Tak więc odpowiedź na twoje pytanie brzmi: "Podczas zapisywania stanu preferencji dysk nie powiedzie się dla twojego konkretnego wywołania commit()." Ponieważ zmiany zostały odzwierciedlone w pamięci, mogą one, ale nie muszą zostać zapisane na dysku przez inne commit() lub apply() przed lub po próbie zapisu dysku (pomyśl o wątkach wyścigowych). Ponieważ nie ma kodu do przywrócenia, aktualizacja pamięci i SharedPreferences są pojedynczymi (per source) innymi komponentami w Twojej aplikacji będą widoczne twoje zmiany, nawet jeśli nie zostały zapisane na dysku.

Podsumowując, pętla kilka razy (nie na zawsze), aby upewnić się, że funkcja commit() zapisuje się na dysku, wydaje się być w porządku, aby przejść przez przerywany problem we/wy, ale byłaby to rzadka sytuacja oparta na I/O, która to nie wyszło. Jeśli potrzebujesz idealnego zakresu zatwierdzania, powinieneś ponownie przeczytać dysk, aby zweryfikować każde wywołanie commit(), które ma wpływ na wydajność i jest przesadne dla wszystkich, z wyjątkiem niewielkiego zestawu sytuacji.

5

commit() może zwrócić wartość false, jeśli wystąpił problem z zapisaniem danych.

Spójrz na różnicy pomiędzy commit() i apply() aby uzyskać jaśniejszy pomysł (wzięte z this site)

apply()

to zapisuje dane w pamięci natychmiast i zapisuje dane do dysku na oddzielny wątek. Nie ma więc możliwości zablokowania głównego wątku (Twoja aplikacja nie zawiesi się).

Jest to preferowana technika, ale jest dostępna tylko od Gingerbread (API 9, Android 2.3).

commit()

Wywołanie to będzie zapisać dane do pliku, jednak proces ten jest przeprowadzone w wątku, który wywołał go, zatrzymując wszystko inne aż do oszczędzania jest kompletna. Zwraca wartość true po pomyślnym zakończeniu, false w przypadku niepowodzenia.

Użyj commit(), jeśli potrzebujesz potwierdzenia sukcesu zapisania danych lub jeśli przygotowujesz urządzenia pre-Gingerbread. commit() jest dostępna od API 1

+0

Wiersz 'jeśli potrzebujesz potwierdzenia sukcesu zapisu twoich danych' o mnie, więc nie potrzebuję informacji o różnicy. – Ircover

11

i może while (editor.commit (!)) {;} być rozwiązaniem dla sukcesu tak?

„popełnić” operacja jest synchroniczna i wykonywane na wątku UI, więc jeśli masz jakieś nienaprawialny błąd, który występuje za każdym razem staram się wykonywać commit, będziemy blokować cały swój wątek UI z tym kodem i użytkownika zobaczy ANR. Niedobrze.
"Zastosuj", z drugiej strony, jest asynchroniczne, więc nie może blokować wątku UI, nawet jeśli wykonasz go na czas nieokreślony.
Dokumentacja mówi bardzo niewiele o możliwych niepowodzeniach operacji "zatwierdzenia" (spójrz tutaj here, here i there). Preferencje są przechowywane w pliku XML przechowywanym w pamięci wewnętrznej, więc jedną z możliwych awarii może być uszkodzony plik XML. Drugi można znaleźć w documentation:

Zauważ, że gdy dwa edytory są modyfikując preferencje w tym samym raz, ostatni zadzwonić popełnić wygrywa.

Niewiele można zrobić w związku z uszkodzonym plikiem i, cóż, nie próbuj modyfikować preferencji z różnych miejsc w tym samym czasie. :)

3

Podejdę do tego problemu z zupełnie innej strony.

Istnieje kilka alternatywnych sposobów radzenia sobie z tym.

To, co robię, to kiedy program jest uruchamiany, I inicjalizuję moją wspólną wartość preferencji na wartość testową dla mnie, aby sprawdzić, czy została zmieniona .

np

editor.putInt("key", -1); 

Następnie w działalności, w których jestem pobierania wartość preferencji:

int mySavedInt = this.pref.getInt("key", howIgetMyInt) 
if(mySavedInt==-1){ 
    // I know it's not my saved int :) and hasn't been set. 
} 

Albo faktycznie wykorzystać wspólną samą preferencję do ustalenia, czy wspólne preferencje ty próby sprawdzania poprawności zostały zaktualizowane.

np.

String getStatus = pref.getString("checkMySharedPreferences", "nil"); 
    if (getStatus.equals("true")) { 
     // DO something. 
    } else { 
     Toast.makeText(this, "Set your preferences", 
       Toast.LENGTH_SHORT).show(); 
    } 

Następnie po ustawieniu udostępnionych preferencji można ustawić tę wartość na „true”:

editor.putString("checkMySharedPreferences", "true"); 
editor.commit(); 

Kolejna propozycja jest zapewnienie przed aktualizacją udostępnionych preferencje sprawdzania poprawności danych. W ten sposób współdzielone ustawienia nie zostaną ustawione, jeśli dane nie są prawidłowe.

if(my data is valid){ 
    my shared preferences 
    commit 
} 

Ostateczna propozycja jest zrobić test cykliczny (jak jesteś niepewny w procesie), a gdy pojawi się dane dla współdzielonych preferencji i zobowiązać go. Sprawdź, czy dane wejściowe użytkownika są równe nowym udostępnionym preferencjom. Chociaż nie uważam tego za konieczne.

I aby rejestrować te zdarzenia, po prostu dodawaj do nich linie dziennika w stosownych przypadkach.

Poza tym, nie wydaje mi się, że dobrym zwyczajem jest zgłaszanie wyjątków, jeśli nie są ustawione, uważam, że zarządzanie przepływem programu może być lepiej obsługiwane za pomocą instrukcji warunkowych, w których oczywiste jest, że będzie błąd runtime. Zapisz obsługę błędów podczas sprawdzania poprawności danych wprowadzanych przez użytkownika.

+0

Mówisz o zapisywaniu powodzenia, ale pytam o przyczynę niepowodzenia zapisu. – Ircover

+0

@Ukryj, jeśli niepokoisz się o przyczynę niepowodzenia awarii, której nie potrzebuję, możesz zastosować logikę cykliczną, o której wspomniałem. To jest prosta kontrola. Sprawdź wprowadzone wartości za pomocą ostatnio zapisanych wartości, jeśli różnią się one, nie zostały zaktualizowane. –

+0

Moja logika ma na celu zapobieganie problemom, które mogą uniemożliwić wykonywanie przez robaka. Podchodziłem do całego problemu z innego punktu widzenia. Czy rozumiesz moje myślenie? Zgadzam się z inną odpowiedzią, dokładnie kontroluj, gdzie zmieniasz swoje wspólne preferencje. –

Powiązane problemy