MonoDroid: ошибка при вызове конструктора пользовательского представления – TwoDScrollView

Я создаю приложение для Android, которое использует специально созданный TwoDScrollView, который можно найти здесь:

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

Этот же класс можно найти на нескольких других веб-сайтах, а другие на Stack Overflow задали вопросы по этому поводу. Я использовал его в предыдущем приложении для Android, которое я создавал с использованием Java / Eclipse, и у меня был успех.

С моим текущим приложением я хотел использовать C # и MonoDroid. Я решил переписать весь класс TwoDScrollView на C #. После его перезаписи, а затем, используя его в XML-макете, я получаю следующие исключения при попытке запустить мой код:

Исправлено System.NotSupportedException. Не удалось активировать экземпляр типа MyProject.TwoDScrollView из встроенного дескриптора 44f4d310.

System.Exception: конструктор не найден для MyProject.TwoDScrollView ::. Ctor (System.IntPtr, Android.Runtime.JniHandleOwnership) …… с последующим текстом.

Мой формат 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> 

В соответствии с инструкциями по следующей ссылке на использование пользовательских представлений в макете XML в MonoDroid: 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 (которую вы можете найти в приведенной выше ссылке). Любая идея о том, что может пойти не так? Я могу опубликовать полный код C # моего TwoDScrollView, если кто-то захочет его увидеть. Это по сути то же самое, что и бит кода 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 .

В Mono для Android все становится еще сложнее. Конструктор Android Callable Wrapper (ACW) вызывается Java и отвечает за создание экземпляра однорангового C # и сопоставление экземпляра Java с экземпляром C # . Однако , если виртуальный метод вызывается из конструктора Java, тогда метод будет отправлен до того, как появится экземпляр C # для вызова метода!

Пусть это немного утонет.

Я не знаю, какой метод запускает сценарий для вашего конкретного кода (фрагмент кода, который вы предоставили, отлично работает), но у нас есть образец, который влияет на этот сценарий: LogTextBox переопределяет свойство TextView.DefaultMovementMethod , а конструктор TextView вызывает Метод getDefaultMovementMethod() . В результате Android пытается вызвать LogTextBox.DefaultMovementMethod до LogTextBox экземпляра LogTextBox .

Итак, что делает Mono для Android? Mono для Android создал ACW и, таким образом, знает, какой тип C # должен использовать метод getDefaultMovementMethod() . То, что у него нет, есть экземпляр, потому что он не был создан. Поэтому Mono для Android создает экземпляр соответствующего типа … через конструктор (IntPtr, JniHandleOwnership) и генерирует ошибку, если этот конструктор не найден.

Как только конструктор TextView (в этом случае) завершит выполнение, будет выполнен конструктор ACW LogTextBox , и в этот момент Mono для Android пойдет «ага! Мы уже создали экземпляр C # для этого экземпляра Java» и затем будем вызывать Соответствующий конструктор на уже созданном экземпляре. Это означает, что для одного экземпляра будут выполняться два конструктора: конструктор (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) { }

У меня была та же проблема с пользовательским представлением изображения, и ответ для 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) { } 
Intereting Posts