przechowywać i pobierać obiekt klasy we wspólnych preferencjach

111

Czy w systemie Android możemy przechowywać obiekt klasy we wspólnych preferencjach i później pobrać obiekt?

Jeśli to możliwe, jak to zrobić? Jeśli nie jest to możliwe, jakie są inne możliwości zrobienia tego?

Wiem, że serializacja to jedna opcja, ale szukam możliwości przy użyciu wspólnych preferencji.

androidGuy
źródło
Dodaję bibliotekę pomocniczą na wypadek, gdyby ktoś jej potrzebował: github.com/ionull/objectify
Tsung Goh
Oto odpowiedź na podobne pytanie.
tpk
Możesz użyć tej biblioteki, która ma wiele wbudowanych funkcji. github.com/moinkhan-in/PreferenceSpider
Moinkhan,

Odpowiedzi:

15

Niemożliwe.

W SharedPrefences SharePreferences.Editor można przechowywać tylko proste wartości

A co szczególnie z klasą, którą musisz zapisać?

Blundell
źródło
1
Dzięki.Chcę przechowywać niektóre składowe danych klasy.I nie chcę przechowywać każdej wartości członków danych przy użyciu wspólnych preferencji.Chcę przechowywać to jako obiekt.Jeśli nie dzielę preferencji, jakie mam inne opcje?
androidGuy,
5
Serializuj go i przechowuj w bazie danych (SQLite) / w pliku płaskim.
Blundell,
5
Odpowiedź nie jest kompletna. Możliwym rozwiązaniem jest przekształcenie pojo w ByteArrayOutPutStream i zapisanie jako String w
SharedPreferences
27
inna opcja jest zapisywana jako json, a następnie mapowana z powrotem. Z GSON lub jackSON jest naprawdę proste
rallat
2
pozwól mi cofnąć mój wehikuł czasu do 2011 roku i to
rozgryźć
324

Tak, możemy to zrobić za pomocą Gson

Pobierz działający kod z GitHub

SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);

Na ratunek

Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(myObject); // myObject - instance of MyObject
prefsEditor.putString("MyObject", json);
prefsEditor.commit();

Za dostać

Gson gson = new Gson();
String json = mPrefs.getString("MyObject", "");
MyObject obj = gson.fromJson(json, MyObject.class);

Aktualizacja 1

Najnowszą wersję GSON można pobrać ze strony github.com/google/gson .

Aktualizacja2

Jeśli używasz Gradle / Android Studio, po prostu umieść następujące w build.gradlesekcji zależności -

implementation 'com.google.code.gson:gson:2.6.2'
Parag Chauhan
źródło
nie działa w moim przypadku. Nawet po umieszczeniu jar w bibliotekach i ustawieniu w ścieżce kompilacji, klasa Gson nie została rozwiązana.
Shirish Herwade
Wyczyść projekt, a następnie wypróbuj @ShirishHerwade
Parag Chauhan
@parag, który również nie działa. Czy możesz mi powiedzieć, jak użyć tego słoika, aby usunąć powyższy błąd. Ponieważ pomyślnie dodałem ten jar w folderze libs, a następnie w „ścieżce kompilacji java” próbowałem również dodać zewnętrzne przechowywanie json na moim pulpicie
Shirish Herwade
7
Ta odpowiedź byłaby jeszcze lepsza, gdyby wspomniała również o swoich ograniczeniach. Jakiego rodzaju przedmioty możemy i nie możemy przechowywać i odzyskiwać w ten sposób? Oczywiście nie będzie działać dla wszystkich klas.
wvdz
3
String json = gson.toJson("MyObject");powinien być obiektem, a nie Stringiem.
Ahmed Hegazy
44

możemy użyć Outputstream do wyprowadzenia naszego Object do pamięci wewnętrznej. I przekonwertuj na ciąg, a następnie zapisz w preferencjach. Na przykład:

    mPrefs = getPreferences(MODE_PRIVATE);
    SharedPreferences.Editor ed = mPrefs.edit();
    ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();

    ObjectOutputStream objectOutput;
    try {
        objectOutput = new ObjectOutputStream(arrayOutputStream);
        objectOutput.writeObject(object);
        byte[] data = arrayOutputStream.toByteArray();
        objectOutput.close();
        arrayOutputStream.close();

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Base64OutputStream b64 = new Base64OutputStream(out, Base64.DEFAULT);
        b64.write(data);
        b64.close();
        out.close();

        ed.putString(key, new String(out.toByteArray()));

        ed.commit();
    } catch (IOException e) {
        e.printStackTrace();
    }

kiedy musimy wyodrębnić Object z Preference. Użyj kodu jak poniżej

    byte[] bytes = mPrefs.getString(indexName, "{}").getBytes();
    if (bytes.length == 0) {
        return null;
    }
    ByteArrayInputStream byteArray = new ByteArrayInputStream(bytes);
    Base64InputStream base64InputStream = new Base64InputStream(byteArray, Base64.DEFAULT);
    ObjectInputStream in;
    in = new ObjectInputStream(base64InputStream);
    MyObject myObject = (MyObject) in.readObject();
Kislingk
źródło
Cześć, wiem, że to zostało wysłane jakiś czas temu, ale czy na pewno kod, który masz do wyodrębnienia przechowywanego obiektu, jest poprawny? Otrzymuję wiele błędów w ostatnich 2 wierszach narzekających na to, jak jawne konstruktory muszą być zdefiniowane, zamiast po prostu mieć „nowy ObjectInputStream (byteArray)”. Dzięki za pomoc!
Wakka Wakka Wakka
Cześć, nagle otrzymuję EOFException na in = new ObjectInputStream (base64InputStream); Piszę to do wspólnych prefs w dokładnie taki sam sposób jak ty. Jak myślisz, co może być nie tak?
marienke
Czy masz jakiś wyjątek, gdy piszesz Object do pref? Z SDK: Zgłoszenie EOFException, gdy program napotka koniec pliku lub strumienia podczas operacji wejściowej.
Kislingk
Uznanie, to najlepsze rozwiązanie tego problemu, z jakim do tej pory się spotkałem. Brak zależności. Należy jednak zauważyć, że aby móc używać ObjectOutput / InputStream dla obiektu, wspomniany obiekt i wszystkie obiekty niestandardowe w nim zawarte muszą implementować interfejs Serializable.
user1112789
8

Miałem ten sam problem, oto moje rozwiązanie:

Mam klasę MyClass i ArrayList <MyClass>, którą chcę zapisać w Shared Preferences. Na początku dodałem do MyClass metodę, która konwertuje ją na obiekt JSON:

public JSONObject getJSONObject() {
    JSONObject obj = new JSONObject();
    try {
        obj.put("id", this.id);
        obj.put("name", this.name);
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return obj;
}

Oto metoda zapisywania elementów obiektu „ArrayList <MyClass>”:

SharedPreferences mPrefs = context.getSharedPreferences("some_name", 0);
    SharedPreferences.Editor editor = mPrefs.edit();

    Set<String> set= new HashSet<String>();
    for (int i = 0; i < items.size(); i++) {
        set.add(items.get(i).getJSONObject().toString());
    }

    editor.putStringSet("some_name", set);
    editor.commit();

A oto metoda na pobranie obiektu:

public static ArrayList<MyClass> loadFromStorage() {
    SharedPreferences mPrefs = context.getSharedPreferences("some_name", 0);

    ArrayList<MyClass> items = new ArrayList<MyClass>();

    Set<String> set = mPrefs.getStringSet("some_name", null);
    if (set != null) {
        for (String s : set) {
            try {
                JSONObject jsonObject = new JSONObject(s);
                Long id = jsonObject.getLong("id"));
                String name = jsonObject.getString("name");
                MyClass myclass = new MyClass(id, name);

                items.add(myclass);

            } catch (JSONException e) {
                e.printStackTrace();
         }
    }
    return items;
}

Zauważ, że StringSet w Shared Preferences jest dostępny od API 11.

Micer
źródło
Rozwiązał mój problem. Chcę coś dodać. Przed pierwszym użyciem musimy sprawdzić, czy zestaw jest pusty. if (set! = null) {for (String s: set) {..}}
xevser
@xevser Dodałem sprawdzanie zerowe zgodnie z sugestią. Dzięki.
Micer
6

Korzystanie z biblioteki Gson:

dependencies {
compile 'com.google.code.gson:gson:2.8.2'
}

Sklep:

Gson gson = new Gson();
//Your json response object value store in json object
JSONObject jsonObject = response.getJSONObject();
//Convert json object to string
String json = gson.toJson(jsonObject);
//Store in the sharedpreference
getPrefs().setUserJson(json);

Odzyskać:

String json = getPrefs().getUserJson();
Ramesh sambu
źródło
Paczka nie jest mechanizmem serializacji ogólnego przeznaczenia. Ta klasa (i odpowiadające jej Parcelable API do umieszczania dowolnych obiektów w paczce) jest zaprojektowana jako wysokowydajny transport IPC. W związku z tym nie jest właściwe umieszczanie danych Przesyłki w trwałym magazynie: zmiany w podstawowej implementacji jakichkolwiek danych w Przesyłce mogą spowodować, że starsze dane staną się nieczytelne.
Marcos Vasconcelos
1

Możesz to zrobić za pomocą PowerPreferencebiblioteki w 3 prostych krokach!

https://github.com/AliAsadi/PowerPreference

1. Utwórz obiekt

Object obj = new Object();

2. Napisz do wspólnych preferencji

PowerPreference.getDefaultFile().put("object",obj);

3. Zdobycie przedmiotu

Object obj = PowerPreference.getDefaultFile()
                            .getObject("object", Object.class);
Ali Asadi
źródło
0

Korzystanie z tego obiektu -> TinyDB - Android-Shared-Preferences-Turbo jest bardzo proste. możesz za jego pomocą zapisać większość powszechnie używanych obiektów, takich jak tablice, liczby całkowite, listy łańcuchów itp

kc ochibili
źródło
Fajnie, ale myślę, że to działa tylko dla typów pierwotnych (String, double, int itp.), A nie dla obiektów niestandardowych (POJOS)
CommonSenseCode
działa teraz dla obiektów niestandardowych, sprawdź
plik
0

Możesz użyć biblioteki Complex Preferences Android - by Felipe Silvestre do przechowywania własnych obiektów. Zasadniczo używa mechanizmu GSON do przechowywania obiektów.

Aby zapisać obiekt do prefs:

User user = new User();
user.setName("Felipe");
user.setAge(22); 
user.setActive(true); 

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(
     this, "mypref", MODE_PRIVATE);
complexPreferences.putObject("user", user);
complexPreferences.commit();

Aby go odzyskać:

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(this, "mypref", MODE_PRIVATE);
User user = complexPreferences.getObject("user", User.class);
Serhii Hrabas
źródło
Paczka nie jest mechanizmem serializacji ogólnego przeznaczenia. Ta klasa (i odpowiadające jej Parcelable API do umieszczania dowolnych obiektów w paczce) jest zaprojektowana jako wysokowydajny transport IPC. W związku z tym nie jest właściwe umieszczanie danych Przesyłki w trwałym magazynie: zmiany w podstawowej implementacji jakichkolwiek danych w Przesyłce mogą spowodować, że starsze dane staną się nieczytelne.
Marcos Vasconcelos
To jest przestarzałe
IgorGanapolsky
0

Możesz użyć GSON, używając Gradle Build.gradle:

implementation 'com.google.code.gson:gson:2.8.0'

Następnie w swoim kodzie, na przykład pary string / boolean z Kotlin:

        val nestedData = HashMap<String,Boolean>()
        for (i in 0..29) {
            nestedData.put(i.toString(), true)
        }
        val gson = Gson()
        val jsonFromMap = gson.toJson(nestedData)

Dodawanie do SharedPrefs:

        val sharedPrefEditor = context.getSharedPreferences(_prefName, Context.MODE_PRIVATE).edit()
        sharedPrefEditor.putString("sig_types", jsonFromMap)
        sharedPrefEditor.apply()

Teraz, aby pobrać dane:

val gson = Gson()
val sharedPref: SharedPreferences = context.getSharedPreferences(_prefName, Context.MODE_PRIVATE)
val json = sharedPref.getString("sig_types", "false")
val type = object : TypeToken<Map<String, Boolean>>() {}.type
val map = gson.fromJson(json, type) as LinkedTreeMap<String,Boolean>
for (key in map.keys) {
     Log.i("myvalues", key.toString() + map.get(key).toString())
}
CAZ
źródło
Paczka nie jest mechanizmem serializacji ogólnego przeznaczenia. Ta klasa (i odpowiadające jej Parcelable API do umieszczania dowolnych obiektów w paczce) jest zaprojektowana jako wysokowydajny transport IPC. W związku z tym nie jest właściwe umieszczanie danych Przesyłki w trwałym magazynie: zmiany w podstawowej implementacji jakichkolwiek danych w Przesyłce mogą spowodować, że starsze dane staną się nieczytelne.
Marcos Vasconcelos
0

Wspólne preferencje wspólne (CURD) SharedPreference: do przechowywania danych w postaci par wartość-klucz z prostą klasą Kotlin.

var sp = SharedPreference(this);

Przechowywanie danych:

Aby przechowywać dane typu String, Int i Boolean, mamy trzy metody o tej samej nazwie i różnych parametrach (Przeciążenie metod).

save("key-name1","string value")
save("key-name2",int value)
save("key-name3",boolean)

Pobierz dane: aby pobrać dane przechowywane w SharedPreferences, użyj następujących metod.

sp.getValueString("user_name")
sp.getValueInt("user_id")
sp.getValueBoolean("user_session",true)

Wyczyść wszystkie dane: Aby wyczyścić całe SharedPreferences, użyj poniższego kodu.

 sp.clearSharedPreference()

Usuń określone dane:

sp.removeValue("user_name")

Wspólna klasa preferencji wspólnych

import android.content.Context
import android.content.SharedPreferences

class SharedPreference(private val context: Context) {
    private val PREFS_NAME = "coredata"
    private val sharedPref: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
    //********************************************************************************************** save all
    //To Store String data
    fun save(KEY_NAME: String, text: String) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putString(KEY_NAME, text)
        editor.apply()
    }
    //..............................................................................................
    //To Store Int data
    fun save(KEY_NAME: String, value: Int) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putInt(KEY_NAME, value)
        editor.apply()
    }
    //..............................................................................................
    //To Store Boolean data
    fun save(KEY_NAME: String, status: Boolean) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putBoolean(KEY_NAME, status)
        editor.apply()
    }
    //********************************************************************************************** retrieve selected
    //To Retrieve String
    fun getValueString(KEY_NAME: String): String? {

        return sharedPref.getString(KEY_NAME, "")
    }
    //..............................................................................................
    //To Retrieve Int
    fun getValueInt(KEY_NAME: String): Int {

        return sharedPref.getInt(KEY_NAME, 0)
    }
    //..............................................................................................
    // To Retrieve Boolean
    fun getValueBoolean(KEY_NAME: String, defaultValue: Boolean): Boolean {

        return sharedPref.getBoolean(KEY_NAME, defaultValue)
    }
    //********************************************************************************************** delete all
    // To clear all data
    fun clearSharedPreference() {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.clear()
        editor.apply()
    }
    //********************************************************************************************** delete selected
    // To remove a specific data
    fun removeValue(KEY_NAME: String) {
        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.remove(KEY_NAME)
        editor.apply()
    }
}

Blog: https://androidkeynotes.blogspot.com/2020/02/shared-preference.html

Hari Shankar S.
źródło
-2

Nie ma sposobu na przechowywanie obiektów w SharedPreferences, co zrobiłem, to utworzyłem publiczną klasę, umieściłem wszystkie potrzebne parametry i utworzyłem setery i gettery, mogłem uzyskać dostęp do moich obiektów,

Ismael ozil
źródło
-3

Czy musisz pobierać obiekt nawet po zamknięciu aplikacji lub po prostu podczas jej działania?

Możesz przechowywać go w bazie danych.
Lub po prostu utwórz niestandardową klasę Application.

public class MyApplication extends Application {

    private static Object mMyObject;
    // static getter & setter
    ...
}

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application ... android:name=".MyApplication">
        <activity ... />
        ...
    </application>
    ...
</manifest>

A potem z każdej czynności wykonaj:

((MyApplication) getApplication).getMyObject();

Nie jest to najlepszy sposób, ale działa.

luc.chante
źródło
-6

Tak, możesz przechowywać i pobierać obiekt za pomocą Sharedpreference

Sukanya
źródło