Android: сохранить карту в SharedPreferences?

Мне нужно сохранить данные на SharedPreferences таким образом, чтобы у меня был такой объект:

{
    "days": [
        {
            "exercises": [
                {
                    "name": "Bench Press",
                    "sets": 3,
                    "reps": 8
                },
                {
                    "name": "Skull Crushers",
                    "sets": 3,
                    "reps": 8
                },
                {
                    "name": "Flys",
                    "sets": 3,
                    "reps": 8
                }
            ]
        },
        {
            "exercises": [
                {
                    "name": "Bench Press",
                    "sets": 3,
                    "reps": 8
                },
                {
                    "name": "Skull Crushers",
                    "sets": 3,
                    "reps": 8
                },
                {
                    "name": "Flys",
                    "sets": 3,
                    "reps": 8
                }
            ]
        }
    ]
}

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

edit: из того, что сказал Advice-Dog, я думаю, что лучше всего использовать gson. Значит ли это, что когда я хочу (например) добавить еще одно упражнение ко второму индексу «дней», я сначала беру объект из настроек, конвертирую его из gson в объект, затем добавляю упражнение, а затем конвертирую его обратно на gson, а потом перезаписать настройки? Я не говорю, что это плохо, я просто хочу знать, нужно ли это делать и целесообразно ли это.

у этой структуры данных есть проблема в том, что нельзя различать дни - и SharedPreferences скорее предназначены для хранения настроек приложения (простых данных); не использовать в качестве базы данных.

Martin Zeitler 04.01.2019 00:33
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
1
2 518
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

При сохранении более сложных типов в Android я бы предложил использовать gson. Gson - это библиотека синтаксического анализа JSON от Google, и даже если вы не используете JSON, вы можете преобразовать свой Objects в строку JSON и легко сохранить ее.

Например, вы можете преобразовать свой список Objects в String следующим образом.

val list : List<MyObject>  // ... add items to your list

// Convert to JSON

val string = gson.toJson(list)

// Store it into Shared Preferences
preferences.putString("list", string).apply()

И тогда вы можете легко вернуть его в такой список.

// Fetch the JSON 

val string = preferences.getString("list", "")

// Convert it back into a List

val list: List<MyObject> = gson.fromJson(string, object : TypeToken<List<MyObject>>() {}.type)

Просто вопрос. Означает ли это, что каждый раз, когда я хочу добавить значение к объекту, я сначала конвертирую json в объект, затем добавляю значение, затем конвертирую его обратно в json, а затем сохраняю предыдущие настройки?

Slaknation 03.01.2019 17:53

@BUInvent Да. Это может показаться расточительным, но это нормально. GSON работает очень быстро, как и SharedPreferences. Вы также можете сохранить локальную копию, обновить ее и сохранить. Таким образом, вы не перечитываете его постоянно, но все зависит от вашего использования.

Advice-Dog 03.01.2019 19:15

Использование JSON - лучшее решение, но вот еще одно решение (просто чтобы добавить еще один способ решения проблемы):

вы можете использовать такие общие ключи настроек:

for((dayIndex, day) in days.withIndex)
    for((exeIndex, exe) in day)
       for((key, value) in exe)
          addExercise(day = dayIndex, exercise = exeIndex, key = key, value = value)


fun addExercise(day: String, exercise: String, key: String, value: String) = 
     preferences.putString("day${day}_exe${exercise}_${key}", value).apply()           

тогда вы можете получить название первого упражнения из Второй день следующим образом:

val first_exercise_second_day = preferences.getString("day2_exe1_name")

и вы можете добавить упражнение к третьему дню следующим образом:

 addExercise(day = "3", exercise = "1", key = "name", value = "Flys")
 addExercise(day = "3", exercise = "1", key = "sets", value = "5")
 addExercise(day = "3", exercise = "1", key = "reps", value = "3")

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

вы можете использовать библиотеку для google ==> Gson добавить это в зависимости в gradle

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

вы можете этой библиотекой преобразовать объект в json как String, затем вы можете сохранить его в общем Pref As String когда вы получаете String из Pref, вы можете преобразовать String в объект

преобразовать json в модель

    /*type of model*/=new Gson().fromJson(/*json string*/,/*type of model*/)

преобразовать модель в json как String

 new Gson().toJson(/*model you want to convert */)===> return String

должен моделировать ту же иерархию для json, где возникают проблемы при преобразовании

Модель для вас json должна быть похожей на эту модель

  public class JSONModel implements Serializable {


    @SerializedName("days")
    private List<Day> mDays;

    public List<Day> getDays() {
        return mDays;
    }

    public void setDays(List<Day> days) {
        mDays = days;
    }

    public class Day {

        @SerializedName("exercises")
        private List<Exercise> mExercises;

        public List<Exercise> getExercises() {
            return mExercises;
        }

        public void setExercises(List<Exercise> exercises) {
            mExercises = exercises;
        }

    }
    public class Exercise {

        @SerializedName("name")
        private String mName;
        @SerializedName("reps")
        private Long mReps;
        @SerializedName("sets")
        private Long mSets;

        public String getName() {
            return mName;
        }

        public void setName(String name) {
            mName = name;
        }

        public Long getReps() {
            return mReps;
        }

        public void setReps(Long reps) {
            mReps = reps;
        }

        public Long getSets() {
            return mSets;
        }

        public void setSets(Long sets) {
            mSets = sets;
        }

    }

}

Другие вопросы по теме