【问题标题】:Using Shared Preferences with arrays将共享首选项与数组一起使用
【发布时间】:2011-12-25 13:06:39
【问题描述】:

编辑: 好的事实证明这段代码正在工作(或多或少)我留在了重置我试图更改的布尔值的行中。不过还是感谢大家的帮助。

当我的应用程序启动时,无法使用 SharedPreferences 读取保存的数组数据。 我的_dPad Boolean 和我的_FreePlay Integer 可以毫无问题地加载、保存和传递到我的_renderer

当我尝试使用一些数组时,问题就开始了 easteregg[] 现在只有 2 个条目,所以显然我可以将它们转换为单独的变量,但我希望添加更多长度更长的 arras,以便作为一个方便的测试示例。

我已经在代码中记录了似乎发生的情况(easteregg[] 设置似乎没有改变)

读取数据:

    // Read saved preferences    
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

    _renderer._dPad = prefs.getBoolean("_dPad", false);                // * works ok *
    _renderer._FreePlay = prefs.getInt("_FreePlay", 1);                // * works ok *
    _renderer.easteregg[0] = prefs.getBoolean("easteregg[0]", false ); // * not working
    _renderer.easteregg[1] = true;                        // * even this is not working

    setRenderer(_renderer);

写入数据:

    public void onDetachedFromWindow() {
    super.onDetachedFromWindow();

    // As good a time as any to save current config
    save = false ; // don't commit if nothing changed.

    SharedPreferences prefs =                       
    PreferenceManager.getDefaultSharedPreferences(getContext());
    SharedPreferences.Editor editor = prefs.edit();

    if (_renderer._dPad != prefs.getBoolean("_dPad",false)){ save = true ;
    editor.putBoolean("_dPad", _renderer._dPad);}

    if (_renderer._FreePlay != prefs.getInt("_FreePlay",1)){ save = true ;
    editor.putInt("_FreePlay", _renderer._FreePlay);}

    editor.putBoolean("easteregg[0]", _renderer.easteregg[0]);

    editor.putBoolean("easteregg[1]", _renderer.easteregg[1]);

    if (save == true){editor.commit();}

}

在 .renderer 类中

    // START SAVE DATA
    public boolean _dPad ; // false no Virtual Pad     *Works Fine*
    public int _FreePlay ;  // 1 = no free play        *Works Fine*
    public boolean[] easteregg = new boolean[2];       *Values don't load or save*
    //public boolean easteregg[]; // tried this first  *CAUSES CRASH*
    // END SAVE DATA

我必须将数组转换为字符串吗?我不知道如何更改它们。

【问题讨论】:

  • 布尔值默认为false,如果没有另外声明。你确定你在某个时候改变了这个值吗?在保存之前和检索之后尝试打印日志语句。
  • 好吧,即使我有“_renderer.easteregg[1] = true;”,他们仍然保持状态。我知道它没有在代码的其他地方更改,因为如果我更改“public boolean[] easteregg = new boolean[2];”到 "public boolean easteregg[]; ={true,true}" 那么这些值肯定是真的。

标签: android arrays string sharedpreferences


【解决方案1】:

我将您的代码放入一个快速活动中,只创建渲染器类的外壳,就像您在上面所做的那样,发现您的保存布尔值是错误的,因此它永远不会提交首选项。

我强制保存为真,然后玩弄它,一切正常。

我建议您在复活节彩蛋中添加支票,就像您对任何其他偏好一样;测试当前值是否与保存的值相同,如果不是,设置保存标志。

【讨论】:

    【解决方案2】:

    我建议将数组保存为单个变量中的字符串。看来你有一个布尔数组。所以循环遍历它以使其成为一系列整数 (0, 1) 或字符串“true”或“false”,然后将其保存为 int 或字符串。

    我怀疑问题可能是您的设置名称包含方括号。我认为在键值名称中,键名必须是有效的变量名。变量名中不允许使用方括号。

    但是我也希望这会引发错误。如果您将设置命名为“easteregg_01”和“easteregg_02”,代码是否有效?

    【讨论】:

    • 首选项键可以是任何有效的字符串。只要他所有的复活节彩蛋都是布尔值,他的代码就没有问题(除了保存标志从未设置过^_^)
    • 天啊!很好的捉迷藏剑客。并感谢您对密钥命名的回答。我可以写一个键“4 * $ = throw(new Error()):%8347”似乎很疯狂。但我想是这样的。 (不是我愿意,但我可以)
    • :-) 哦,显示代码片段的危险。我的保存标志正在设置中
    【解决方案3】:

    最好的解决方案是将您的数组转换为 JSON 字符串并将其存储为首选项值。如果你有少量数据,你也可以坚持使用 android 提供的 org.json 类。如果您有更多数据,GSON 拉解析器会更好,因为它使用拉解析器。如果你真的很懒,你可以拿起我的小型数据绑定库,然后做:

    String jsonState = preferences.getString(GAME_STATE, null);
    StateStorage storage = JSONUnmarshaller.unmarshall(new JsonReader(new              
                        StringReader(jsonState)), StateStorage.class);
    

    它会为你实例化java类并填写数据。并保存:

    SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
    StringWriter writer = new StringWriter();
    JsonWriter jsonWriter = new JsonWriter(writer);
    
    JSONMarshaller.marshall(jsonWriter, ss);
    editor.putString(GAME_STATE, writer.toString());
    editor.commit();
    

    数据绑定库可在 github 上或从 maven Central 获得:

    https://github.com/ko5tik/jsonserializer

    PS:目前我致力于注入偏好值(目前仅限于原语): https://github.com/ko5tik/andject

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-26
      • 1970-01-01
      • 2014-12-03
      • 2013-07-25
      • 1970-01-01
      • 2014-05-07
      • 2016-09-05
      • 2018-01-25
      相关资源
      最近更新 更多