On May 16, 2012, at 3:01 AM, Igor Russkih wrote:
> It seems SimpleAdapter is broken (found this in 4.2 alpha), 4.2.1 release
> also have this issue:
This is a "regression" that won't be fixed; see:
http://lists.ximian.com/pipermail/monodroid/2012-May/010250.html
https://bugzilla.xamarin.com/show_bug.cgi?id=2147
The problem is one of preserving object identity between VMs. For example,
consider the following code:
var list = new JavaList<object>();
JavaList is a java.util.ArrayList, in which every value is referenced in the
Java VM.
var value = new XElement (/* ... */);
list.Add (value);
So we've just added an XElement instance to a Java-side list. Okay... So what
should the following do:
var v = list [0];
object.ReferenceEquals (v, value);
Should object.ReferenceEquals() be true or false?
Prior to 4.2.1, it would be false, and `v` would refer to an
Android.Runtime.JavaObject instance (which isn't even public!), leading to all
manner of Reflection-hackery to get back the original value. This is pretty bad.
The "good" news was that if it was a Dictionary instead of an XElement, it
would be "deep marshaled" into Java: the Dictionary contents would be copied
into a java.util.HashMap. The fundamental problem remained, though: `list[0]`
would not return `value`, it would (at best) give a separate copy. Worse (for
varying values of "worse"), there'd be a _ton_ of global references held during
that marshaling operation, none of which would get collected until the entire
object graph was collectable by both VMs.
In short, it worked, but it was a mess. It led to "bizarre" behavior, and
increased gref use.
(Truly, I should have fixed that for 4.0, but I wasn't able to carve out the
time...)
The fix? Use types which won't be implicitly wrapped into an
Android.Runtime.JavaObject, i.e. the (public) Android.Runtime collection types.
> var settings_data = new List<IDictionary<string, object>>();
var settings_data = new JavaList<IDictionary<string, object>>();
>
> sa = Resources.ObtainTypedArray(Resource.Array.settings_text);
> sa_icons =
> Resources.ObtainTypedArray(Resource.Array.settings_icons);
>
> for (int i = 0; i < sa.Length(); i++)
> {
> var item = new Dictionary<string, object>();
var item = new JavaDictionary<string, object>();
> item["text"] = sa.GetString(i);
> item["icon"] = sa_icons.GetResourceId(i, 0);
> settings_data.Add(item);
> }
>
> this.ListAdapter = new SimpleAdapter(this, settings_data,
> Resource.Layout.list_item_icon_text, new String[] { "text",
> "icon" },
> new int[] { Resource.Id.text, Resource.Id.icon });
Two changes to two lines should fix your exception.
The above still keeps grefs around for longer than absolutely necessary; you
can use some `using`s to further decrease the lifetime of the collections, as
outlined at:
http://lists.ximian.com/pipermail/monodroid/2012-May/010250.html
Thanks,
- Jon
_______________________________________________
Monodroid mailing list
[email protected]
UNSUBSCRIBE INFORMATION:
http://lists.ximian.com/mailman/listinfo/monodroid