【问题标题】:Android: Save map to SharedPreferences?Android:将地图保存到 SharedPreferences?
【发布时间】:2019-05-28 05:31:31
【问题描述】:

我需要将数据保存到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,但我不确定这是否是使用内部存储器的最佳选择。我想我只是在寻找关于我的最佳选择的指导。

编辑:根据Advice-Dog 所说,我认为我最好的选择是使用gson。那么这是否意味着当我想(例如)将另一个练习添加到“天”的第二个索引时,我将首先从首选项中获取对象,将其从 gson 转换为对象,然后添加练习,然后将其转换回gson,然后覆盖首选项?我并不是说这很糟糕,我只是想知道这是否应该做以及是否可取。

【问题讨论】:

  • 这个数据结构有一个问题,就是不能改变天数 - 而SharedPreferences 是为了保留应用程序设置(简单数据);不要被滥用为数据库。

标签: java android dictionary kotlin sharedpreferences


【解决方案1】:

在 Android 中保存更复杂的类型时,我建议使用gson。 Gson 是 Google 的 JSON 解析库,即使您不使用 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,然后保存之前的首选项?
  • @BUInvent 是的。这听起来可能很浪费,但完全没问题。 GSON 非常快,SharedPreferences 也是如此。您还可以保留本地副本、更新并保存。所以你不会经常把它读回来,而是取决于你的使用情况。
【解决方案2】:

使用 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")

但是要找到空的一天或空的练习号,您必须获取所有共享偏好的键并使用正则表达式或循环

【讨论】:

    【解决方案3】:

    您可以使用 google 库 ==> Gson 在 gradle 的依赖项中添加这个

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

    你可以这个库将对象转换为 json 作为字符串然后你可以将它保存在共享的 Pref As String 当您从 Pref 获取 String 时,您可以将 String 转换为对象

    将 json 转换为模型

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

    将模型转换为字符串格式的json

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

    【讨论】:

      猜你喜欢
      • 2016-06-23
      • 2016-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-26
      • 2021-07-04
      相关资源
      最近更新 更多