android SharedReferences空键、值和集<>;-角落案例

android SharedReferences空键、值和集<>;-角落案例,android,sharedpreferences,android-preferences,Android,Sharedpreferences,Android Preferences,一直在广泛测试SharedReferences框架。虽然大多数都能如期工作,但我遇到过一些案例,我想知道它们背后的原因是什么。我给出了一些测试,所有测试都通过-它们的常见设置是: Context ctx; SharedPreferences prefs; Editor ed; protected void setUp() throws Exception { super.setUp(); ctx = getContext(); prefs = PreferenceMana

一直在广泛测试
SharedReferences
框架。虽然大多数都能如期工作,但我遇到过一些案例,我想知道它们背后的原因是什么。我给出了一些测试,所有测试都通过-它们的常见设置是:

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();
}
现在奇怪的是:

  • 当我把一个空值放进去时,我必须用一个空的默认值要求它把它取回来——如果默认值是非空的,我就把这个默认值取回来。即使默认值与我输入的类型不同。适用于
    字符串
    (但我可以返回一个布尔值,例如):

  • 我可以很容易地将
    集合
    放在prefs内:

    @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)); // !
        }
    }
    
    但是我在我的日志中看到了如下内容:
    org.xmlpull.v1.XmlPullParserException:Map value without name属性:boolean
    -请参阅以获取讨论。我想知道这是否与
    null
    键有关编辑:它是相关的-复制器:

    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)
    
    显然,当抛出异常时,首选项被清除(坏)

  • 所以我的问题是:我所说的行为真的是这样吗(或者我错过了一些愚蠢的事情)?背后的动机是什么(尤其是空值行为)?是否有文件记录并保证保持不变?或者可能发生变化?第二点是疏忽吗

  • 它是

  • 是我不懂泛型:

  • 在这里发布了一个问题:(在谷歌群组中以通常的noop结果开始了一次搜索之后)。事实上,截至2014年1月7日,该版本标记为未来版本:)

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