共用方式為


限制

由於 Android 上的應用程式需要在建置程式期間產生 Java Proxy 類型,因此無法在運行時間產生所有程式代碼。

相較於桌面Mono,以下是 Xamarin.Android 限制:

有限的動態語言支援

每當 Android 執行時間需要叫用 Managed 程式代碼時,都需要 Android 可呼叫包裝函 式。 Android 可呼叫包裝函式會根據 IL 的靜態分析,在編譯時期產生。 此結果的凈結果:您無法在任何需要 Java 類型子類別化(包括間接子類別化)的情況下使用動態語言 (IronPython、IronRuby 等),因為編譯時期無法擷取這些動態類型,以產生必要的 Android 可呼叫包裝函式。

有限的 Java 產生支援

必須產生 Android 可呼叫包裝函式 ,Java 程式代碼才能呼叫 Managed 程式代碼。 根據預設,Android 可呼叫包裝函式只會包含已宣告的建構函式和方法,這些建構函式會覆寫虛擬 Java 方法(亦即具有 RegisterAttribute),或實作 Java 介面方法(介面同樣具有 Attribute)。

在 4.1 版本之前,無法宣告其他方法。 在 4.1 版本中,ExportExportField 自定義屬性可用來宣告 Android 可呼叫包裝函式內的 Java 方法和欄位。

遺漏建構函式

除非使用建構函式,否則 ExportAttribute 建構函式仍然棘手。 產生 Android 可呼叫包裝函式建構函式的演算法是,如果下列狀況,將會發出 Java 建構函式:

  1. 所有參數類型都有Java對應
  2. 基類會宣告相同的建構函式 – 這是必要的,因為Android可呼叫包裝函 式必須 叫用對應的基類建構函式;沒有預設自變數可以使用(因為無法輕易判斷Java內應該使用的值)。

例如,請參考下列類別:

[Service]
class MyIntentService : IntentService {
    public MyIntentService (): base ("value")
    {
    }
}

雖然這看起來完全合乎邏輯,但發行組建中產生的 Android 可呼叫包裝函式將不會包含預設建構函式。 因此,如果您嘗試啟動此服務(例如 Context.StartService,它會失敗:

E/AndroidRuntime(31766): FATAL EXCEPTION: main
E/AndroidRuntime(31766): java.lang.RuntimeException: Unable to instantiate service example.MyIntentService: java.lang.InstantiationException: can't instantiate class example.MyIntentService; no empty constructor
E/AndroidRuntime(31766):        at android.app.ActivityThread.handleCreateService(ActivityThread.java:2347)
E/AndroidRuntime(31766):        at android.app.ActivityThread.access$1600(ActivityThread.java:130)
E/AndroidRuntime(31766):        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1277)
E/AndroidRuntime(31766):        at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(31766):        at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(31766):        at android.app.ActivityThread.main(ActivityThread.java:4745)
E/AndroidRuntime(31766):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(31766):        at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(31766):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
E/AndroidRuntime(31766):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
E/AndroidRuntime(31766):        at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(31766): Caused by: java.lang.InstantiationException: can't instantiate class example.MyIntentService; no empty constructor
E/AndroidRuntime(31766):        at java.lang.Class.newInstanceImpl(Native Method)
E/AndroidRuntime(31766):        at java.lang.Class.newInstance(Class.java:1319)
E/AndroidRuntime(31766):        at android.app.ActivityThread.handleCreateService(ActivityThread.java:2344)
E/AndroidRuntime(31766):        ... 10 more

因應措施是宣告預設建構函式、使用 ExportAttribute裝飾它,並設定 ExportAttribute.SuperStringArgument

[Service]
class MyIntentService : IntentService {
    [Export (SuperArgumentsString = "\"value\"")]
    public MyIntentService (): base("value")
    {
    }

    // ...
}

泛型 C# 類別

僅部分支援泛型 C# 類別。 存在下列限制:

  • 泛型型別不得使用 [Export][ExportField。 嘗試這樣做會產生 XA4207 錯誤。

    public abstract class Parcelable<T> : Java.Lang.Object, IParcelable
    {
        // Invalid; generates XA4207
        [ExportField ("CREATOR")]
        public static IParcelableCreator CreateCreator ()
        {
            ...
    }
    
  • 泛型方法不得使用 [Export][ExportField]

    public class Example : Java.Lang.Object
    {
    
        // Invalid; generates XA4207
        [Export]
        public static void Method<T>(T value)
        {
            ...
        }
    }
    
  • [ExportField] 無法在傳回 void的方法上使用 :

    public class Example : Java.Lang.Object
    {
        // Invalid; generates XA4208
        [ExportField ("CREATOR")]
        public static void CreateSomething ()
        {
        }
    }
    
  • 泛型型 別的實例不得 從Java程式碼建立。 它們只能安全地從Managed程式代碼建立:

    [Activity (Label="Die!", MainLauncher=true)]
    public class BadGenericActivity<T> : Activity
    {
        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);
        }
    }
    

部分 Java 泛型支援

Java 泛型系結支援有限。 特別是,衍生自另一個泛型(非具現化)類別之泛型實例類別的成員會公開為 Java.Lang.Object。 例如, Android.Content.Intent.GetParcelableExtra 方法會傳回 Java.Lang.Object。 這是因為清除的Java泛型。 我們有一些類別不適用此限制,但會手動調整。