gpt4 book ai didi

android - MonoDroid : Error when calling constructor of custom view - TwoDScrollView

转载 作者:IT王子 更新时间:2023-10-28 23:53:39 30 4
gpt4 key购买 nike

我正在构建一个使用此处找到的定制 TwoDScrollView 的 Android 应用程序:

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

可以在其他几个网站上找到该类的引用,Stack Overflow 上的其他人也提出了有关它的问题。我在以前使用 Java/Eclipse 构建的 Android 应用程序中使用它,并且取得了成功。

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

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

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 中的自定义 View 的说明: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 版本中相同的构造函数(您可以在上面的链接中找到)。知道可能出了什么问题吗?如果有人愿意,我可以发布我的 TwoDScrollView 的完整 C# 代码。它基本上与 Java 代码一点一点的相同——除了用 C# 重写。

感谢您的帮助!

最佳答案

恭喜!你遇到了一个泄漏的抽象。 :-/

问题是这样的:for better or worse ,来自构造函数的虚方法调用调用最派生的方法实现。 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 for Android 中,事情变得更加...复杂。 Android Callable Wrapper (ACW)的构造函数由 Java 调用并负责创建 peer C# instance and mapping the Java instance to the C# instance . 然而,如果从 Java 构造函数中调用了一个虚方法,那么该方法将在有一个 C# 实例调用该方法之前被调度!

让它沉下去一点。

我不知道哪种方法会触发您的特定代码的场景(您提供的代码 fragment 可以正常工作),但我们确实有一个适用于这种场景的示例:LogTextBox overrides TextView.DefaultMovementMethod属性(property),以及 TextView constructor invokes the getDefaultMovementMethod() method .结果是 Android 尝试在 LogTextBox 实例甚至存在之前调用 LogTextBox.DefaultMovementMethod

那么 Android 的 Mono 有什么作用? Mono for Android 创建了 ACW,因此知道应该将 getDefaultMovementMethod() 方法委托(delegate)给哪个 C# type。它没有实例,因为尚未创建实例。因此,Android 的 Mono 会通过 (IntPtr, JniHandleOwnership) 构造函数创建适当类型的实例,如果找不到该构造函数,则会生成错误。

一旦(在这种情况下)TextView 构造函数完成执行,LogTextBox 的 ACW 构造函数将执行,此时 Mono for Android 将“啊哈!我们'已经为这个 Java 实例创建了一个 C# 实例”,然后然后在已经创建的实例上调用适当的构造函数。这意味着对于单个实例,将执行两个构造函数:(IntPtr, JniHandleOwnership) constructor ,和(后来)(Context, IAttributeSet, int) constructor .

关于android - MonoDroid : Error when calling constructor of custom view - TwoDScrollView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10593022/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com