On Aug 9, 2012, at 10:50 AM, subsembly <a.se...@subsembly.com> wrote: > I am trying to understand what exactly happens when I am using an > Android.Widget.ArrayAdapter<string> for my list views and spinners. > Considering the following sample code from an Activity: > > string[] vs = new string[] { "one", "two", "three" } > ArrayAdapter<string> aa = new ArrayAdapter<string>(this, > Android.Resource.Layout.SimpleSpinnerItem, vs); > Spinner s = (Spinner)this.FindViewById(Resource.Id.myspinner); > s.Adapter = aa; > > I know that on the Java side, the ArrayAdapter needs a Java list with Java > objects. How is Mono for Android converting my C# string to the Java objects > that Java needs?
Lots of JNI glue. ;-) The array is "deep copied" into Java. The string[] is marshaled into a Java-side array via JNIEnv.NewObjectArray(), which in this case will allocate a Java-side java.lang.String[], then copy each element of the C# string[] into the Java String[] via JNIEnv.NewString(). No grefs are required. If you were instead dealing with a builtin type such as `int`, the values would instead be converted into a java.lang.Integer[], and the values are (again) "deep copied." No grefs are required. When using a Java.Lang.Object subclass, a new Java-side array will be created, and each element of the Java-side array will reference the Android Callable Wrapper for the C# instance. Each instance will have a gref, but they'd have a gref _anyway_; the underlying Java array will not have a gref. When using any other managed type, a new Java-side java.lang.Object[] array will be created, with each element referring to an internal mono.android.JavaObject instance which will reference the managed instance. Each JavaObject instance will also take out a gref. > Later in my code when I use > > Java.Lang.Object o = s.SelectedItem; > > How does the returned Java object relate to my original string? `o` will be a Java.Lang.String instance, which will contain a copy of your original string value. This will also cause a gref to be allocated (for referential equality); if grefs are an issue, you'll want to dispose of it ASAP. > And how do I get back to the original string? The original string instance? You don't. (Thus `object.ReferenceEquals()` is out.) The original string value? `o.ToString()`. You can thus do: string item; using (var o = s.SelectedItem) item = o.ToString(); > Finally: Is there a better (faster, less memory using) way than using an > ArrayAdapter<string> at all? The tradeoff is in performance. For strings, ArrayAdapter<string> should be good -- the entire collection is stored in Java, making Java-side object lookup fast. There's some overhead in duplicated strings, but there's no way to avoid this: as soon as Java code calls ArrayAdapter<String>.getItem(), it'll get a Java-side copy of the string anyway; there's no way to avoid that copy. If you were dealing with some other type, specifically a managed type, you'd want to consider forgoing ArrayAdapter<T> altogether and using BaseAdapter<T> instead. This will cause item lookup to be _slower_ (due to the transition to managed code), but gref counts will also be lower and there will be fewer instances allocated. - Jon _______________________________________________ Monodroid mailing list Monodroid@lists.ximian.com UNSUBSCRIBE INFORMATION: http://lists.ximian.com/mailman/listinfo/monodroid