简体   繁体   中英

Xamarin MultiSelectListPreference InvalidCastException

Currently I'm trying to save a List of String in the shared preferences storage of Android. I use the shared preferences and therefore can use the MultiSelectListPreference of Android itself. Saving the value is not the issue, but maybe it's the cause. The issue itself starts when I try to read the value. At that very moment Android gives a ArrayList to the Xamarin code and Xamarin should convert this to a C# List. And then I get the following InvalidCastException:

[MonoDroid] UNHANDLED EXCEPTION:
[MonoDroid] System.InvalidCastException: Cannot cast from source type to destination type.
[MonoDroid] at (wrapper castclass) object.__castclass_with_cache (object,intptr,intptr) <0x00068>
[MonoDroid] at Android.Runtime.JavaSet`1<string>.FromJniHandle (intptr,Android.Runtime.JniHandleOwnership) <0x0008f>
[MonoDroid] at Android.Content.ISharedPreferencesInvoker.GetStringSet (string,System.Collections.Generic.ICollection`1<string>) <0x0015b>
[MonoDroid] at canvastix.MultiSelectListPreference.OnDialogClosed (bool) <0x0009f>
[MonoDroid] at Android.Preferences.DialogPreference.n_OnDialogClosed_Z (intptr,intptr,bool) <0x0003f>
[MonoDroid] at (wrapper dynamic-method) object.4bc48339-d8f3-443a-a584-0088f55fe375 (intptr,intptr,bool) <0x00043>
[mono] 
[mono] Unhandled Exception:
[mono] System.InvalidCastException: Cannot cast from source type to destination type.
[mono]   at (wrapper castclass) object:__castclass_with_cache (object,intptr,intptr)
[mono]   at Android.Runtime.JavaSet`1[System.String].FromJniHandle (IntPtr handle, JniHandleOwnership transfer) [0x00000] in <filename unknown>:0 
[mono]   at Android.Content.ISharedPreferencesInvoker.GetStringSet (System.String key, ICollection`1 defValues) [0x00000] in <filename unknown>:0 
[mono]   at canvastix.MultiSelectListPreference.OnDialogClosed (Boolean positiveResult) [0x00000] in <filename unknown>:0 
[mono]   at Android.Preferences.DialogPreference.n_OnDialogClosed_Z (IntPtr jnienv, IntPtr native__this, Boolean positiveResult) [0x00000] in <filename unknown>:0 
[mono]   at (wrapper dynamic-method) object:4bc48339-d8f3-443a-a584-0088f55fe375 (intptr,intptr,bool)
[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidCastException: Cannot cast from source type to destination type.
[mono-rt]   at (wrapper castclass) object:__castclass_with_cache (object,intptr,intptr)
[mono-rt]   at Android.Runtime.JavaSet`1[System.String].FromJniHandle (IntPtr handle, JniHandleOwnership transfer) [0x00000] in <filename unknown>:0 
[mono-rt]   at Android.Content.ISharedPreferencesInvoker.GetStringSet (System.String key, ICollection`1 defValues) [0x00000] in <filename unknown>:0 
[mono-rt]   at canvastix.MultiSelectListPreference.OnDialogClosed (Boolean positiveResult) [0x00000] in <filename unknown>:0 
[mono-rt]   at Android.Preferences.DialogPreference.n_OnDialogClosed_Z (IntPtr jnienv, IntPtr native__this, Boolean positiveResult) [0x00000] in <filename unknown>:0 
[mono-rt]   at (wrapper dynamic-method) object:4bc48339-d8f3-443a-a584-0088f55fe375 (intptr,intptr,bool)

I use the following piece of code to read the value in a Activity. Nothing special:

Button button = FindViewById<Button> (Resource.Id.button);
button.Click += delegate {
    //Read value
    ISharedPreferences Prefs = PreferenceManager.GetDefaultSharedPreferences (this);
    ICollection<String> list = Prefs.GetStringSet("list", new List<String>());
    Toast.MakeText(this, "Total items: " + list.Count, ToastLength.Short).Show();
};

I use the following code to show the MultiSelectListPreference in a fragment:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <MultiSelectListPreference
        android:key="list"
        android:entries="@array/Entries"
        android:entryValues="@array/Values" />
</PreferenceScreen>

This is the layout of the Activity:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <fragment
        class="XamarinBugReadStringsetPreference.MainFragment"
        android:id="@+id/fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <Button
        android:id="@+id/button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Read and Show" />
</LinearLayout>

And last but not least, these are the values of the list:

<?xml version="1.0" encoding="UTF-8" ?>
<resources>
    <string-array name="Entries">
        <item>1</item>
        <item>2</item>
    </string-array>
    <string-array name="Values">
        <item>Item 1</item>
        <item>Item 2</item>
    </string-array>
</resources>

Feel free to try it out. In the manifest I have set the minSdkVersion to 15 and targetSdkVersion to 19.

My taught after a week is that it must be a bug in Xamarin. So if you find a work-around that would be great as well.

You may have run into this Xamarin bug: https://bugzilla.xamarin.com/show_bug.cgi?id=13141 Which looks like it was marked as fixed in January.

(But see the latest in this discussion in the Xamarin Forum): http://forums.xamarin.com/discussion/6531/preferencemanager-getstringset-keeps-crashing

If you are not using the latest Xamarin builds you may want to try that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM