MonoDroid:调用自定义视图构造函数时错误 - TwoDScrollView [英] MonoDroid: Error when calling constructor of custom view - TwoDScrollView

查看:227
本文介绍了MonoDroid:调用自定义视图构造函数时错误 - TwoDScrollView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我建立一个使用定制TwoDScrollView在这里发现了一个Android应用程序:

I am building an Android application that uses the custom-built TwoDScrollView found here:

<一个href="http://blog.gorges.us/2010/06/android-two-dimensional-scrollview/">http://blog.gorges.us/2010/06/android-two-dimensional-scrollview/

这同一个类中可以发现,在其他一些网站引用,和其他人对堆栈溢出问关于它的问题。我用它在previous的Andr​​oid应用程序,我是建设使用Java / Eclipse中,和我有成功。

This same class can be found referenced at several other websites, and others on Stack Overflow have asked questions with regard to it. I was using it in a previous Android application that I was building using Java/Eclipse, and I was having success.

使用我当前的应用程序,我想用C#和MonoDroid。我决定重写在C#中的整个TwoDScrollView类。改写它,然后在一些布局XML使用它之后,我尝试运行我的code时,遇到下列情况除外:

With my current application, I wanted to use C# and MonoDroid. I decided to rewrite the entire TwoDScrollView class in C#. After rewriting it, and then using it in some layout XML, I get the following exceptions when trying to run my code:

System.NotSupportedException已被抛出。无法激活   例如从原生手柄44f4d310类型MyProject.TwoDScrollView的。

System.NotSupportedException has been thrown. Unable to activate instance of type MyProject.TwoDScrollView from native handle 44f4d310.

System.Exception的:没有构造发现   MyProject.TwoDScrollView ::。构造函数(System.IntPtr,   Android.Runtime.JniHandleOwnership)......更多的文本   如下......

System.Exception: No constructor found for MyProject.TwoDScrollView::.ctor(System.IntPtr, Android.Runtime.JniHandleOwnership) ......with more text that follows....

我的布局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说明:<一href="http://docs.xamarin.com/android/advanced_topics/using_custom_views_in_a_layout">http://docs.xamarin.com/android/advanced_topics/using_custom_views_in_a_layout

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

The constructors to the TwoDScrollView class look as follows:

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版本(你可以找到在上面的链接)。关于什么可以去错了你知道吗?我可以张贴我的TwoDScrollView的完整的C#code。如果有人想看到它。它本质上是相同位的Java code位 - 除了改写在C#

The same constructors exist in the C# version as in the Java version (which you can find at the above link). Any idea on what could be going wrong? I can post the full C# code of my TwoDScrollView if anyone would like to see it. It's essentially the same as the Java code bit for bit - except rewritten in C#.

感谢您的帮助!

推荐答案

恭喜!你已经打了一个漏水的抽象。 : - /

Congratulations! You've hit a leaky abstraction. :-/

问题是这样的:<一href="https://www.securecoding.cert.org/confluence/display/java/MET05-J.+Ensure+that+constructors+do+not+call+overridable+methods">for更好或更坏,虚方法调用从构造函数调用最衍生的方法实现。 C#是相同的Java在这方面;考虑下面的程序:

The problem is this: for better or worse, virtual method calls from constructors invoke the most derived method implementation. C# is the same as Java in this respect; consider the following program:

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()方法被调用之前的派生构造函数执行。

That is, the Derived.M() method is invoked before the Derived constructor has executed.

在单声道为Android,事情变得更加复杂...。该<一href="http://docs.xamarin.com/android/advanced_topics/architecture/android_callable_wrappers">Android可调用包装(ACW)的构造是由Java的调用,并负责创建的<一个href="http://docs.xamarin.com/android/advanced_topics/garbage_collection#Cross-VM_Object_Collections">peer C#实例和映射Java实例到C#实例。 然而的,如果一个虚拟的方法是从Java的构造函数调用,然后该方法将被派遣之前有一个C#实例时!调用该方法的

In Mono for Android, things get more...complicated. The Android Callable Wrapper (ACW)'s constructor is invoked by Java and is responsible for creating the peer C# instance and mapping the Java instance to the C# instance. However, if a virtual method is invoked from the Java constructor, then the method will be dispatched before there is a C# instance to invoke the method upon!

让一个有点下沉。

我不知道哪种方法触发该方案为您的特定code(在code片段您提供正常工作),但我们有一个样品其打这样的情景:<一href="https://github.com/xamarin/monodroid-samples/blob/master/ApiDemo/Text/LogTextBox.cs#L26">LogTextBox <一href="https://github.com/xamarin/monodroid-samples/blob/master/ApiDemo/Text/LogTextBox.cs#L45">overrides在<一个href="http://androidapi.xamarin.com/?link=P:Android.Widget.TextView.DefaultMovementMethod">TextView.DefaultMovementMethod属性,并在<一href="https://github.com/android/platform_frameworks_base/blob/gingerbread-release/core/java/android/widget/TextView.java#L366"><$c$c>TextView构造函数调用 getDefaultMovementMethod()方法。其结果是,Android的试图调用 LogTextBox.DefaultMovementMethod LogTextBox 实例的存在。

I don't know which method is triggering the scenario for your specific code (the code fragment you provided works fine), but we do have a sample which hits this scenario: LogTextBox overrides the TextView.DefaultMovementMethod property, and the TextView constructor invokes the getDefaultMovementMethod() method. The result is that Android tries to invoke LogTextBox.DefaultMovementMethod before a LogTextBox instance even exists.

那么,是什么单声道为Android吗?单声道为Android创造了ACW,从而知道哪些C#的键入的的 getDefaultMovementMethod()方法应该委托给。它不具有是一个实例,因为一个尚未创建。因此,单声道为Android通过(IntPtr的,JniHandleOwnership)构造函数创建相应类型的实例...,并生成如果这个构造函数不能发现错误。

So what does Mono for Android do? Mono for Android created the ACW, and thus knows which C# type the getDefaultMovementMethod() method should be delegated to. What it doesn't have is an instance, because one hasn't been created. So Mono for Android creates an instance of the appropriate type...via the (IntPtr, JniHandleOwnership) constructor, and generates an error if this constructor cannot be found.

一旦(在这种情况下)的TextView 的构造函数执行完毕时, LogTextBox 的ACW构造函数会执行,在这一点单声道为Android会去啊!我们已经创建了一个C#实例这个Java实例,并会的然后的调用,对已经创建的实例适当的构造。这意味着对于一个实例,两个构造函数将被执行:在<一href="https://github.com/xamarin/monodroid-samples/blob/master/ApiDemo/Text/LogTextBox.cs#L28"><$c$c>(IntPtr, JniHandleOwnership)构造和(后下)的<一个href="https://github.com/xamarin/monodroid-samples/blob/master/ApiDemo/Text/LogTextBox.cs#L41"><$c$c>(Context, IAttributeSet,INT)构造。

Once the (in this case) TextView constructor finishes executing, the LogTextBox's ACW constructor will execute, at which point Mono for Android will go "aha! we've already created a C# instance for this Java instance", and will then invoke the appropriate constructor on the already created instance. Meaning that for a single instance, two constructors will be executed: the (IntPtr, JniHandleOwnership) constructor, and (later) the (Context, IAttributeSet, int) constructor.

这篇关于MonoDroid:调用自定义视图构造函数时错误 - TwoDScrollView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆