I did not mean to complain at Nobu - sorry if I sounded harsh :) I just wanted to point out that my question was not so much *what *happens but *why *- and also raise awareness to this buggy and unintuitive behavior- or maybe have someone explain why this is so.
Should we post a bug report ? On Wednesday, October 30, 2013 8:23:46 PM UTC+2, Kristopher Micinski wrote: > > Your question seems more to deal with intention rather than > complaining. I believe that Nobu's response was merely interpreting > the implementation and trying to interpret it, so there's no use in > trying to complain at him for providing a guess at something he didn't > even write. > > kris > > > On Wed, Oct 30, 2013 at 2:02 PM, Palmer Eldritch > <[email protected]<javascript:>> > wrote: > > > > On Wednesday, October 30, 2013 7:44:17 PM UTC+2, Nobu Games wrote: > >> > >> I quickly peeked into the source code and well, this is the way how it > is > >> programmed. When an exception occurs while the preferences data file > gets > >> read, SharedPreferences sets internally an empty map so you start from > >> scratch. I even dug a bit deeper. The XML serializer just ignores NULL > keys > >> and creates XML output that cannot be properly read anymore through the > map > >> deserialization method which seems to expect an existing key value. > > > > > > My question is really why was it allowed to insert a null key in the > first > > place - why not throw a NPE immediately (and say so in the docs) ? > > If you read my links (point 3 here) you will see that null keys are > > perfectly valid : - they fail only on loading the prefs - taking down > > everything with them > > They should either fix deserialization or prohibit null keys > >> > >> > >> As for why it has been programmed like that... I think the reasoning > may > >> be that preferences are not deemed to be of so much importance that it > >> should make the app crash in case of failure. This error state is > silently > >> discarded and you start over with the defaults. I think that's a > reasonable > >> approach since any app should be able to start over with empty > preferences. > > > > > > > > Not at all - Shared Preferences is a documented persistence mechanism - > it > > is as reasonable as deleting a database without even saying so > > > >> > >> > >> In this particular case you may have discovered a tiny bug you may want > to > >> report. But to be honest, using null keys is a pretty unusual thing to > do. > > > > > > Not so (either by mistake or not). > > See the discussions in the SO. Some more I suspect they may have to do > with > > null keys : > > > > sharedpreferences - Android - Shared Preferences are lost sometimes - > Stack > > Overflow > > > http://stackoverflow.com/questions/7943573/android-shared-preferences-are-lost-sometimes > > > android - Shared Preferences get lost after shutting down device or > killing > > the app - Stack Overflow > > > http://stackoverflow.com/questions/9803838/shared-preferences-get-lost-after-shutting-down-device-or-killing-the-app#comment12495021_9803838 > > > > >> > >> > >> On Wednesday, October 30, 2013 5:48:12 AM UTC-5, Palmer Eldritch wrote: > >>> > >>> The preferences are apparently cleared when one tries to load them > when > >>> there is a null key which is bad ! Reproducer : > >>> > >>> 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 > >>> } > >>> } > >>> > >>> 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) > > > >>> > >>> Posted in SO here and in the relevant thread here - but still no > answers > >>> > >>> Any ideas ? > > > > -- > -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/android-developers?hl=en --- You received this message because you are subscribed to the Google Groups "Android Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/groups/opt_out.

