2013-01-02 8 views
7

Używam SharedPreferences do pisania i późniejszego czytania wartości w różnych działaniach w mojej aplikacji. Kiedyś pracowało się dobrze, ale ostatnio wygląda na to, że nie było sincronizowane. Mam na myśli, że piszę wartość, ale wtedy druga aktywność nadal odczytuje starą wartość. Czasami działa poprawnie. Każdy pomysł?SharedPreferences czyta stare wartości

EDIT: To jest przykładowy kod:

Po pierwsze, z wątku:

SharedPreferences prefs = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE); 
SharedPreferences.Editor editor = prefs.edit(); 
editor.putInt("ComandToDo", value); 
editor.commit(); 
... some code later: 
alarmmanager.set(AlarmManager.RTC_WAKEUP, Miliseconds, sender); 

W odbiorniku alarmowego:

SharedPreferences prefs = contexto.getSharedPreferences("MyPrefs", Context.MODE_PRIVATE); 
int value = prefs.getInt("ComandToDo", -1);  

I tu pojawia się problem, bo „wartości "nie jest wartością zapisaną w wątku.

+3

robisz je odczytuje i zapisuje w różnych wątków? Opublikuj kod, w którym czytasz i piszesz. – Ralgha

+0

tak, różne wątki, czynności, odbiorniki radiowe, ... wiele miejsc. Wyobraź sobie: wątek zapisuje wartość w SharedPreferences. Następnie tworzy alarm. Odbiornik radiowy odczytuje tę wartość kilka minut później. Ale nie jest aktualizowany! – Ton

+0

Musisz zobaczyć kod, w którym również czytasz i zapisujesz wartości. – Ralgha

Odpowiedz

2
  1. SharedPreferences dokumentowane są nie do pracy w poprzek procesów http://developer.android.com/reference/android/content/SharedPreferences.html „Uwaga: obecnie ta klasa nie obsługuje wykorzystania w wielu procesach ta zostanie dodana później.”

  2. Ta odpowiedź zaleca enkapsulacji danych do dostawcy zawartości, a dyskusja uważa również kilka innych opcji, w tym wspólną SQLite: https://stackoverflow.com/a/5265556/1665128

  3. Trzeba również Plain Old pliki w systemie plików. Wykorzystaliśmy je w kilku projektach, z blokowaniem, bez żadnych problemów. Może być również opcją dla ciebie.

+0

Dzięki! Jeszcze jedno pytanie. To naprawdę nie są dwa procesy na siebie nawzajem. Jest to tylko jeden wątek, który rejestruje coś do zrobienia i uruchamia i alarm (może kilka godzin później). Tak proste! Czy istnieje sposób na wymuszenie zapisu na dysk i pozostawienie buforowania? Dzięki – Ton

+0

@Ton: wygląda na to, że system mobilny nie robi tak szybko, jak to możliwe. Na wszelki wypadek, czyż nie jest to logiczny błąd, mimo całej prostoty? Coś szalonego, jak trzeci fragment kodu, który nadpisuje zatwierdzenie, kontrolowanie jakoś nie sięgania do punktu zapisu (wyjątek w "jakimś kodzie później"), itd. Jak o pieprzeniu go za pomocą Log.d? (Interesujące byłoby również zajrzenie do kodu Android, teraz nie mam żadnych przydatnych funkcji, ale AFAIK, za kulisami te preferencje są przechowywane w plikach.) –

+3

Od tego pisania [SharedPreferences] (http: //developer.android.com/reference/android/content/SharedPreferences.html) nadal mówi "Uwaga: obecnie ta klasa nie obsługuje używania wielu procesów. Zostanie dodana później." ALE, API 11 dodał [MODE_MULTI_PROCESS] (http://developer.android.com/reference/android/content/Context.html#MODE_MULTI_PROCESS), który "po ustawieniu, plik na dysku zostanie sprawdzony pod kątem modyfikacji, nawet jeśli udostępniony instancja preferencji jest już załadowana w tym procesie ... "Tak więc powinieneś móc używać' getSharedPreferences (PREFS_NAME, Context.MODE_MULTI_PROCESS) ' – Anonsage

0

Piszecie w pliku preferencji "MyPrefs", a następnie próbujesz odczytać z pliku "PerfilDeSonidoPreferencias". Proszę odczytać/zapisać z tego samego pliku preferencji.

+0

Niestety, był to tylko błąd podczas kopiowania-wklejania. Oba są "MyPrefs" lub cokolwiek innego. – Ton

4

Oto, co napotkałem i co zrobiłem, aby to naprawić.

Wywołałem alarm z działania, a w odbiorniku-odbiorniku tego alarmu aktualizowałem Preferencje współdzielone, które były odczytywane przy każdym uruchomieniu aplikacji.

Po uruchomieniu alarmu, za każdym razem, gdy uruchomiono aplikację, otrzymywał stare wartości, które zostały ustawione tylko z tego działania. Nie zostały uwzględnione żadne zmiany z Broadcast-Receiver.

Sztuką jest, aby ustawić podziałem Preferencje jak MODE_MULTI_PROCESS

Zazwyczaj używamy MODE_PRIVATE, ale zrobić w następujący sposób:

SharedPreferences prefs = this.getSharedPreferences("Preferences", MODE_MULTI_PROCESS); 

Uwaga: Po tryb zmienia się w kodzie, zaleca się wyczyść dane aplikacji, aby uniknąć problemów podczas debugowania.

EDIT: MODE_MULTI_PROCESS potrzeba min API 11

Przed API 11 obejście, które mogę myśleć jest stworzenie bazy danych z 2 kolumny KEY & WARTOŚCI. Dostęp do niej można uzyskać z innych modułów.

+0

Dziękuję, ale myślę, że potrzebujesz przynajmniej API 11 dla tego – Ton

+0

O tak. Przepraszam, zapomniałem o tym wspomnieć. –

+0

Dokumenty mówią, że nie używają tego teraz, ponieważ są przestarzałe, ponieważ działają niezawodnie. –

0

Po prostu użyj IntentService zamiast BroadcastReceiver.To jest praca dla mnie.

ServiceClass:

public class ServiceClass extends IntentService { 

    public NotificationPopupService(String name) { 
     super(name); 
    } 

    public NotificationPopupService(){ 
     super("YOU_DEFAULT_NAME"); 
    } 

    @Override 
    protected void onHandleIntent(Intent intent) { 
     SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); 

     do magic... 
    } 
} 

W Tobie AndroidManifest.xml plik w tagu aplikacji:

<service android:name="ServiceClass"/> 

Tworzenie alarm:

intent = new Intent(context, ServiceClass.class); 
pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); 
// magic after 2 seconds after the creation of alarm 
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 2000, pendingIntent);