MonoDroid:调用自定义视图的构造函数时出错 – TwoDScrollView

我正在构build一个使用定制的TwoDScrollView在这里find的Android应用程序:

http://blog.gorges.us/2010/06/android-two-dimensional-scrollview/

这个类可以在其他几个网站上find,Stack Overflow的其他人也提出了一些问题。 我在之前使用Java / Eclipse构build的Android应用程序中使用了它,而且我取得了成功。

用我目前的应用程序,我想使用C#和MonoDroid。 我决定用C#重写整个TwoDScrollView类。 重写后,然后在一些布局XML中使用它,当我尝试运行我的代码时,出现以下exception:

System.NotSupportedException已被抛出。 无法从本地句柄44f4d310激活types为MyProject.TwoDScrollView的实例。

System.Exception:没有为MyProject.TwoDScrollView ::。ctor(System.IntPtr,Android.Runtime.JniHandleOwnership)find构造函数……更多的文本后面….

我的布局XML如下所示:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <myproject.TwoDScrollView android:layout_width="fill_parent" android:layout_height="fill_parent"> </myproject.TwoDScrollView> </RelativeLayout> 

按照以下链接中关于在MonoDroid中使用布局XML中的自定义视图的说明: http ://docs.xamarin.com/android/advanced_topics/using_custom_views_in_a_layout

TwoDScrollView类的构造函数如下所示:

 public TwoDScrollView(Context context) : base(context) { initTwoDScrollView(); } public TwoDScrollView(Context context, IAttributeSet attrs) : base(context, attrs) { initTwoDScrollView(); } public TwoDScrollView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle) { initTwoDScrollView(); } 

C#版本中存在与Java版本相同的构造函数(可以在上面的链接中find)。 任何想法可能会出错? 如果有人想看,我可以发布我的TwoDScrollView完整的C#代码。 它本质上与Java代码的位相同 – 除了在C#中重写。

感谢您的帮助!

恭喜! 你已经打了抽象的抽象。 : – /

问题是: 无论好坏 ,来自构造函数的虚方法调用都会调用最为派生的方法实现。 C#在这方面与Java相同; 考虑下面的程序:

 using System; class Base { public Base () { Console.WriteLine ("Base..ctor"); M (); } public virtual void M () { Console.WriteLine ("Base.M"); } } class Derived : Base { public Derived () { Console.WriteLine ("Derived..ctor"); } public override void M () { Console.WriteLine ("Derived.M"); } } static class Demo { public static void Main () { new Derived (); } } 

运行时,输出是:

 Base..ctor Derived.M Derived..ctor 

也就是说, Derived.M()方法在Derived构造函数执行之前被调用。

在Android的单声道,事情变得更复杂。 Android Callable Wrapper(ACW)的构造函数由Java调用,负责创build对等C#实例并将Java实例映射到C#实例 。 但是 ,如果从Java构造函数调用虚拟方法,那么将在调用方法之前调度该方法,然后再调用该方法!

让它沉入一点。

我不知道哪个方法触发你的特定代码的场景(你提供的代码片段工作正常),但是我们有一个样本来触及这个场景: LogTextBox 覆盖 TextView.DefaultMovementMethod属性, TextView构造函数调用getDefaultMovementMethod()方法 。 其结果是Android甚至在LogTextBox实例存在之前试图调用LogTextBox.DefaultMovementMethod

那么Android的Mono是做什么的? Android的Mono创build了ACW,因此知道应该委派哪个C# typesgetDefaultMovementMethod()方法。 它没有的是一个实例,因为一个没有被创build。 所以Android的Mono通过(IntPtr, JniHandleOwnership)构造函数创build适当types的实例,并且如果找不到该构造函数,则会生成一个错误。

一旦(在本例中) TextView构造函数完成执行, LogTextBox的ACW构造函数将执行,此时,Android的Mono将会“aha!我们已经为这个Java实例创build了一个C#实例”, 然后调用已经创build的实例上相应的构造函数。 这意味着对于单个实例,将执行两个构造函数: (IntPtr, JniHandleOwnership)构造函数和(稍后) (Context, IAttributeSet, int)构造函数 。

错误消息说:

System.Exception: No constructor found for MyProject.TwoDScrollView::.ctor(System.IntPtr, Android.Runtime.JniHandleOwnership)

尝试添加一个像它说的构造函数,看看是否有帮助:

public TwoDScrollView (IntPtr a, JniHandleOwnership b) : base (a, b) { }

我有一个自定义的ImageView相同的问题和答案jpobst肯定解决了这个问题完全:

 public CircularImageView(Context context) :base(context) { init (context, null, 0); } public CircularImageView(Context context, IAttributeSet attrs) : base(context, attrs) { init (context, attrs, Resource.Attribute.circularImageViewStyle); } public CircularImageView(Context context, IAttributeSet attrs, int defStyle) :base(context, attrs, defStyle) { init(context, attrs, defStyle); } public CircularImageView (IntPtr a, JniHandleOwnership b) : base (a, b) { }