Използваме Mono за Android и искаме да използваме няколко персонализирани подкласа на изглед, които сме написали в Java Android. Създадохме C# "мост" клас, за да изложим Java класа чрез JNI. Отмените на метода и персонализираните методи, които изложихме, работят добре, когато се извикват от C# през мостовия клас на C#, но когато използваме класа в XML оформление (чрез препращане към напълно квалифицираното пространство от имена на java за изгледа), изглежда никога не извиква конструктор чрез C#, така че типът C# не се задава правилно.
XML оформление
<merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.example.widget.ImageView:id="@+id/custom_view" />
</merge>
C# "Bridge" клас конструктори
namespace Example.Widgets {
[Register ("com/example/widget/ImageView", DoNotGenerateAcw=true)]
public class ImageView : global::Android.Widget.ImageView {
private new static IntPtr class_ref = JNIEnv.FindClass("com/example/widget/ImageView");
private static IntPtr id_ctor_Landroid_content_Context_;
private static IntPtr id_ctor_Landroid_content_Context_Landroid_util_AttributeSet_;
private static IntPtr id_ctor_Landroid_content_Context_Landroid_util_AttributeSet_I;
...
protected override IntPtr ThresholdClass {
get {
return ImageView.class_ref;
}
}
protected override Type ThresholdType {
get {
return typeof(ImageView);
}
}
protected ImageView (IntPtr javaReference, JniHandleOwnership transfer) : base (javaReference, transfer) {
}
// --V-- this should get called by the android layout inflater, but it never does (nor do any of the other public constructors here)
[Register (".ctor", "(Landroid/content/Context;Landroid/util/AttributeSet;)V", "")]
public ImageView (Context context, IAttributeSet attrs) : base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer)
{
Log.Debug("ImageView","Calling C# constructor (Landroid/content/Context;Landroid/util/AttributeSet;)V");
if (base.Handle != IntPtr.Zero)
{
return;
}
if (base.GetType () != typeof(ImageView))
{
base.SetHandle (JNIEnv.CreateInstance (base.GetType (), "(Landroid/content/Context;Landroid/util/AttributeSet;)V", new JValue[]
{
new JValue (JNIEnv.ToJniHandle (context)),
new JValue (JNIEnv.ToJniHandle (attrs))
}), JniHandleOwnership.TransferLocalRef);
return;
}
if (ImageView.id_ctor_Landroid_content_Context_Landroid_util_AttributeSet_ == IntPtr.Zero)
{
ImageView.id_ctor_Landroid_content_Context_Landroid_util_AttributeSet_ = JNIEnv.GetMethodID (ImageView.class_ref, "<init>", "(Landroid/content/Context;Landroid/util/AttributeSet;)V");
}
base.SetHandle (JNIEnv.NewObject (ImageView.class_ref, ImageView.id_ctor_Landroid_content_Context_Landroid_util_AttributeSet_, new JValue[]
{
new JValue (JNIEnv.ToJniHandle (context)),
new JValue (JNIEnv.ToJniHandle (attrs))
}), JniHandleOwnership.TransferLocalRef);
}
[Register (".ctor", "(Landroid/content/Context;)V", "")]
public ImageView (Context context) : base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer) {
...
}
[Register (".ctor", "(Landroid/content/Context;Landroid/util/AttributeSet;I)V", "")]
public ImageView (Context context, IAttributeSet attrs, int defStyle) : base (IntPtr.Zero, JniHandleOwnership.DoNotTransfer) {
...
}
...
Java клас
package com.example.widget;
public class ImageView extends android.widget.ImageView {
//--V-- This constructor DOES get called here (in java)
public ImageView(Context context, AttributeSet attrs) {
super(context, attrs);
Log.d(TAG, "Called Java constructor (context, attrs)");
...
}
}
Когато спрем на точка на прекъсване в програмата, виждаме, че локалният за нашия изглед на изображение е от тип Android.Widgets.ImageView, но съдържа стойността {com.example.widget.ImageView @4057f5d8. Смятаме, че типът трябва да показва и Example.Widgets.ImageView, но не можем да разберем как да накараме .NET да използва този тип вместо наследения тип Android ( Android.Widgets.ImageView).
Някакви идеи как да накарате .NET да извиква правилно конструктори, когато изгледи, изложени чрез JNI, се използват в XML оформление?
Благодаря предварително