其他分享
首页 > 其他分享> > android SharedPreferences空键,值和集合<?>-极端情况

android SharedPreferences空键,值和集合<?>-极端情况

作者:互联网

正在广泛测试SharedPreferences框架.尽管大多数作品都可以像我期望的那样,但我遇到了一些情况,我想知道它们背后的原因是什么.我通过了一些测试,它们的通用设置是:

Context ctx;
SharedPreferences prefs;
Editor ed;
protected void setUp() throws Exception {
    super.setUp();
    ctx = getContext();
    prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
    ed = prefs.edit();
}
protected void tearDown() throws Exception {
    if (ed != null) ed.clear().commit();
    super.tearDown();
}

现在的怪异点:

>当我输入一个空值时,我必须使用默认的空值来找回它-如果默认值是非空值,我将把这个默认值找回来.即使默认类型与我输入的类型不同.也适用于String和Set< String>. (但是我可以返回一个布尔值):

public void testNullString() {
    ed.putString("string_key", null); // putString() and putStringSet() only
    ed.commit();
    assertTrue(prefs.contains("string_key"));
    assertEquals(null, prefs.getString("string_key", null));
    // if I specify a non null default I get this default back, not null
    assertEquals("a string", prefs.getString("string_key", "a string"));
    // *even if I ask for a boolean*
    assertEquals(true, prefs.getBoolean("string_key", true));
}

>我可以轻松地将Set< Integer>在偏好中:

@SuppressWarnings("unchecked")
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void testNullStringSetsRaw() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        @SuppressWarnings("rawtypes")
        final Set integerHashSet = new HashSet();
        integerHashSet.add(1);
        ed.putStringSet("set_key", integerHashSet);
        ed.commit();
        final Set<String> defValues = new HashSet<String>();
        defValues.add("a string");
        Set<String> s = prefs.getStringSet("set_key", defValues);
        final String msg = "The set I put in: " + integerHashSet
            + " and what I got out :" + s;
        Log.e(TAG, msg); // the same - [1]
        assertTrue(msg, integerHashSet.equals(s));
        assertTrue(s.contains(1)); // !
    }
}

>空键有什么关系?它们似乎是完全合法的密钥:

public void testNullKeyNonNullString() {
    final String NULL_KEY = null;
    ed.putString(NULL_KEY, "a string");
    ed.commit();
    assertTrue("Contains null key", prefs.contains(NULL_KEY));
    assertEquals("Retrieve the value giving null default", "a string",
        prefs.getString(NULL_KEY, null));
    assertEquals("Retrieve the value giving default", "a string",
        prefs.getString(NULL_KEY, "a string" + "blah"));
    try {
        // no deal !
        prefs.getBoolean(NULL_KEY, true);
        fail("Expected CCE");
    } catch (ClassCastException e) {}
}

但是我在日志中看到了类似以下内容:org.xmlpull.v1.XmlPullParserException:不带名称属性的映射值:布尔值-参见android getSharedPreferences error: Map value without name attribute: boolean进行讨论.我想知道这是否与空键有关.编辑:它是相关的-复制者:

public class XmlExceptionTest extends AndroidTestCase {

    /** Run it twice - on the second run the exception is thrown */
    public void testXmlException() {
        Context ctx = getContext();
        SharedPreferences prefs = PreferenceManager
            .getDefaultSharedPreferences(ctx);//exception thrown here(line 18)
        // and apparently it clears the prefs as the condition below is false
        if (prefs.contains("run_once")) { // false
            Log.w("XmlExceptionTest",
                "contains null key :" + prefs.contains(null));
        }
        Editor e = prefs.edit();
        e.putBoolean("run_once", true).commit();
        e.putString(null, "I put a sting with null key").commit();
        assertTrue("Contains null", prefs.contains(null));
        PreferenceManager.getDefaultSharedPreferences(ctx); // exception
        // NOT thrown here  - why ? - apparently there is a static factory
        // returning the instance it already constructed
        // e.clear().commit(); // this eliminates the exception
    }
}

例外情况:

W/ApplicationContext(): getSharedPreferences
W/ApplicationContext(): org.xmlpull.v1.XmlPullParserException: Map value without name attribute: string
W/ApplicationContext():     at com.android.internal.util.XmlUtils.readThisMapXml(XmlUtils.java:521)
W/ApplicationContext():     at com.android.internal.util.XmlUtils.readThisValueXml(XmlUtils.java:733)
W/ApplicationContext():     at com.android.internal.util.XmlUtils.readValueXml(XmlUtils.java:667)
W/ApplicationContext():     at com.android.internal.util.XmlUtils.readMapXml(XmlUtils.java:470)
W/ApplicationContext():     at android.app.ContextImpl.getSharedPreferences(ContextImpl.java:361)
W/ApplicationContext():     at android.preference.PreferenceManager.getDefaultSharedPreferences(PreferenceManager.java:348)
W/ApplicationContext():     at gr.uoa.di.android.helpers.test.XmlExceptionTest.testXmlException(XmlExceptionTest.java:18)
W/ApplicationContext():     at java.lang.reflect.Method.invokeNative(Native Method)
W/ApplicationContext():     at java.lang.reflect.Method.invoke(Method.java:521)
W/ApplicationContext():     at junit.framework.TestCase.runTest(TestCase.java:154)
W/ApplicationContext():     at junit.framework.TestCase.runBare(TestCase.java:127)
W/ApplicationContext():     at junit.framework.TestResult$1.protect(TestResult.java:106)
W/ApplicationContext():     at junit.framework.TestResult.runProtected(TestResult.java:124)
W/ApplicationContext():     at junit.framework.TestResult.run(TestResult.java:109)
W/ApplicationContext():     at junit.framework.TestCase.run(TestCase.java:118)
W/ApplicationContext():     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
W/ApplicationContext():     at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
W/ApplicationContext():     at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:520)
W/ApplicationContext():     at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)

并且显然在抛出异常时清除了首选项(坏坏坏)

所以我的问题是:确实是我所陈述的行为(或者我错过了一些愚蠢的事情)吗?其背后的动机是什么(尤其是空值行为)?是否已记录在案并保证保持不变-否则可能会更改?第二点是疏忽吗?

Test project.

解决方法:

> in the code
>是我不了解泛型:

07001

>在这里发布问题:http://code.google.com/p/android/issues/detail?id=63463(在Google网上论坛中按常规Noop结果启动discussion之后).实际上,从2014年1月7日开始,该问题被标记为“未来版本” :)

Test project.

标签:sharedpreferences,android-preferences,android
来源: https://codeday.me/bug/20191122/2060919.html