сохранить и получить объект класса в общих предпочтениях


111

Можем ли мы в Android сохранить объект класса в общих предпочтениях и получить объект позже?

Если можно, как это сделать? Если это невозможно, каковы другие возможности сделать это?

Я знаю, что сериализация - это один из вариантов, но я ищу возможности с использованием общих предпочтений.


Я добавляю вспомогательную библиотеку на случай, если она кому-то понадобится: github.com/ionull/objectify
Tsung Goh


Вот ответ на аналогичный вопрос.
tpk


Вы можете использовать эту библиотеку, в которую встроено множество функций. github.com/moinkhan-in/PreferenceSpider
Moinkhan

Ответы:


15

Невозможно.

В SharedPrefences SharePreferences.Editor можно хранить только простые значения.

Что конкретно в классе вам нужно сохранить?


1
Спасибо. Я хочу сохранить некоторые члены данных класса. И я не хочу хранить каждое значение членов данных с использованием общих предпочтений. Я хочу сохранить его как объект. Если не общие предпочтения, какие у меня другие варианты?
androidGuy

5
Сериализируйте его и сохраните в базе данных (SQLite) / в плоском файле.
Blundell

5
Ответ неполный. Возможное решение - преобразовать pojo в ByteArrayOutPutStream и сохранить как String в SharedPreferences
rallat 06

27
другой вариант - сохранить его как json, а затем сопоставить его. С GSON или jackSON действительно просто
rallat 07

2
позвольте мне вернуть мою машину времени в 2011 год и разобраться в этом
Бланделл

324

Да, мы можем сделать это с помощью Gson

Скачать рабочий код с GitHub

SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);

Для сохранения

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

Для получения

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

Update1

Последнюю версию GSON можно загрузить с github.com/google/gson .

Обновление2

Если вы используете Gradle / Android Studio, просто введите следующее в build.gradleраздел зависимостей -

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

не работает в моем случае. Даже после помещения jar в библиотеки и установки пути сборки класс Gson не разрешается.
Шириш Хервэйд

Очистите проект, затем попробуйте @ShirishHerwade
Chauhan

@parag, который тоже не работает. Не могли бы вы рассказать мне, как использовать эту банку для удаления вышеуказанной ошибки. Поскольку я успешно добавил этот jar-файл в папку libs, а затем в «путь сборки java», я также попытался добавить json с внешним хранением на свой рабочий стол
Шириш Хервэйд

7
Этот ответ был бы даже лучше, если бы также упоминались его ограничения. Какие объекты можно и нельзя хранить и извлекать таким образом? Очевидно, это не будет работать для всех классов.
wvdz

3
String json = gson.toJson("MyObject");должен быть объект, а не строка.
Ахмед Хегази

44

мы можем использовать Outputstream для вывода нашего объекта во внутреннюю память. И преобразовать в строку, а затем сохранить в предпочтении. Например:

    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();
    }

когда нам нужно извлечь объект из предпочтений. Используйте код, как показано ниже

    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();

Привет, я знаю, что это было опубликовано некоторое время назад, но уверены ли вы, что у вас есть код для извлечения сохраненного объекта? Я получаю несколько ошибок в последних двух строках, жалуясь на то, как нужно определять явные конструкторы, а не просто иметь «новый ObjectInputStream (byteArray)». Спасибо за помощь!
Wakka Wakka Wakka

Привет, у меня внезапно возникает исключение EOFException на in = new ObjectInputStream (base64InputStream); Я пишу это в общие настройки точно так же, как и вы. Как вы думаете, что может быть не так?
Мариенке

Есть ли у вас исключение, когда вы пишете Object в pref? Из SDK: выбрасывается EOFException, когда программа обнаруживает конец файла или потока во время операции ввода.
Кислингк

Престижность, это лучшее решение, которое я когда-либо встречал для этой проблемы. Никаких зависимостей. Однако следует отметить, что для того, чтобы иметь возможность использовать ObjectOutput / InputStream для объекта, указанный объект и все настраиваемые объекты в нем должны реализовывать интерфейс Serializable.
user1112789

8

У меня была такая же проблема, вот мое решение:

У меня есть класс MyClass и ArrayList <MyClass>, которые я хочу сохранить в общих настройках. Сначала я добавил в MyClass метод, который преобразует его в объект 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;
}

Тогда вот способ сохранения объекта «ArrayList <MyClass> items»:

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();

А вот метод получения объекта:

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;
}

Обратите внимание, что StringSet в общих настройках доступен с API 11.


Решил мою проблему. Я хочу кое-что добавить. Для первого использования мы должны проверить, является ли набор нулевым. if (set! = null) {for (String s: set) {..}}
xevser

@xevser Я добавил нулевую проверку, как было предложено. Спасибо.
Micer

6

Использование библиотеки Gson:

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

Хранить:

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);

Получить:

String json = getPrefs().getUserJson();

Parcel не является универсальным механизмом сериализации. Этот класс (и соответствующий Parcelable API для размещения произвольных объектов в Parcel) разработан как высокопроизводительный транспорт IPC. Таким образом, нецелесообразно помещать какие-либо данные Parcel в постоянное хранилище: изменения в базовой реализации любых данных в Parcel могут сделать старые данные нечитаемыми.
Маркос Васконселос,

1

Вы можете сделать это с помощью PowerPreferenceбиблиотеки за 3 простых шага!

https://github.com/AliAsadi/PowerPreference

1. Создать объект

Object obj = new Object();

2. Напишите в общие настройки

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

3. Получение объекта

Object obj = PowerPreference.getDefaultFile()
                            .getObject("object", Object.class);

0

Используя этот объект -> TinyDB - Android-Shared-Preferences-Turbo, все очень просто. вы можете сохранить с ним большинство часто используемых объектов, таких как массивы, целые числа, списки строк и т. д.


Круто, но я думаю, что это работает только для примитивных типов (String, double, int и т.д.), а не для пользовательских объектов (POJOS)
CommonSenseCode 06

теперь он работает для пользовательских объектов, проверьте ReadMe, он был обновлен
kc ochibili

0

Вы можете использовать Комплексные настройки Android - библиотеку Фелипе Сильвестре для хранения ваших пользовательских объектов. По сути, он использует механизм GSON для хранения объектов.

Чтобы сохранить объект в 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();

И чтобы вернуть его:

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(this, "mypref", MODE_PRIVATE);
User user = complexPreferences.getObject("user", User.class);

Parcel не является универсальным механизмом сериализации. Этот класс (и соответствующий Parcelable API для размещения произвольных объектов в Parcel) разработан как высокопроизводительный транспорт IPC. Таким образом, нецелесообразно помещать какие-либо данные Parcel в постоянное хранилище: изменения в базовой реализации любых данных в Parcel могут сделать старые данные нечитаемыми.
Маркос Васконселос,

Это устарело
Игорь Ганапольский

0

Вы можете использовать GSON, используя Gradle Build.gradle:

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

Затем в вашем коде, например, пары строка / логическое значение с Kotlin:

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

Добавление в SharedPrefs:

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

Теперь, чтобы получить данные:

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())
}

Parcel не является универсальным механизмом сериализации. Этот класс (и соответствующий Parcelable API для размещения произвольных объектов в Parcel) разработан как высокопроизводительный транспорт IPC. Таким образом, нецелесообразно помещать какие-либо данные Parcel в постоянное хранилище: изменения в базовой реализации любых данных в Parcel могут сделать старые данные нечитаемыми.
Маркос Васконселос,

0

Общие общие предпочтения (CURD) SharedPreference: хранить данные в виде пар значение-ключ с помощью простого класса Kotlin.

var sp = SharedPreference(this);

Хранение данных:

Для хранения данных String, Int и Boolean у нас есть три метода с одинаковым именем и разными параметрами (перегрузка метода).

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

Получение данных: для получения данных, хранящихся в SharedPreferences, используйте следующие методы.

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

Очистить все данные: чтобы очистить все SharedPreferences, используйте приведенный ниже код.

 sp.clearSharedPreference()

Удалить определенные данные:

sp.removeValue("user_name")

Общий класс общих предпочтений

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()
    }
}

Блог: https://androidkeynotes.blogspot.com/2020/02/shared-preference.html


-2

Невозможно хранить объекты в SharedPreferences. Я создал общедоступный класс, поместил все необходимые параметры и создал сеттеры и геттеры, я смог получить доступ к своим объектам,


-3

Вам нужно получить объект даже после завершения работы приложения или просто во время его работы?

Вы можете сохранить его в базе данных.
Или просто создайте собственный класс приложения.

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>

А затем из каждого занятия делайте:

((MyApplication) getApplication).getMyObject();

Не совсем лучший способ, но он работает.


-6

Да. Вы можете сохранить и извлечь объект, используя Sharedpreference.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.