Sdílet prostřednictvím


Omezení

Vzhledem k tomu, že aplikace v Androidu vyžadují generování typů proxy v Javě během procesu sestavení, není možné vygenerovat veškerý kód za běhu.

Jedná se o omezení Xamarin.Android v porovnání s desktopovým Mono:

Omezená podpora dynamického jazyka

Obálky s možností volání pro Android jsou potřeba pokaždé, když modul runtime Androidu potřebuje vyvolat spravovaný kód. Obálky s možností volání pro Android se generují v době kompilace na základě statické analýzy IL. Čistý výsledek tohoto: V žádném scénáři, ve kterém je vyžadováno podtřídy typů Javy (včetně nepřímé podtřídy), nemůžete použít dynamické jazyky (IronPython, IronRuby atd.), protože neexistuje způsob extrakce těchto dynamických typů v době kompilace, aby se vygenerovaly potřebné obálky s možností volání Pro Android.

Omezená podpora generování Javy

Aby kód Java mohl volat spravovaný kód, je potřeba vygenerovat obálky pro Android Callable Wrappers . Ve výchozím nastavení budou volatelné obálky androidu obsahovat (určité) deklarované konstruktory a metody, které přepíší virtuální metodu Java (tj. má RegisterAttribute) nebo implementuje metodu rozhraní Java (rozhraní má Attributepodobně).

Před vydáním verze 4.1 nelze deklarovat žádné další metody. Ve verzi Export 4.1 lze pomocí vlastních ExportField atributů deklarovat metody a pole Jazyka Java v rámci obálky volatelné pro Android.

Chybějící konstruktory

Konstruktory zůstávají složité, pokud ExportAttribute se nepoužívají. Algoritmus pro generování konstruktorů obálky s možností volání pro Android spočívá v tom, že konstruktor Jazyka Java se vygeneruje v následujících případech:

  1. Pro všechny typy parametrů existuje mapování Java.
  2. Základní třída deklaruje stejný konstruktor – To je povinné, protože obálka s možností volání pro Android musí vyvolat odpovídající konstruktor základní třídy; nelze použít žádné výchozí argumenty (protože neexistuje žádný snadný způsob, jak určit, jaké hodnoty se mají použít v Javě).

Představte si například následující třídu:

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

I když to vypadá dokonale logické, výsledný obálka pro Android volatelná v buildech release nebude obsahovat výchozí konstruktor. Pokud se tedy pokusíte spustit tuto službu (např. Context.StartServicese nezdaří:

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

Alternativním řešením je deklarovat výchozí konstruktor, doplnit ho ExportAttributepomocí a nastavit ExportAttribute.SuperStringArgument:

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

    // ...
}

Obecné třídy jazyka C#

Obecné třídy jazyka C# jsou podporovány pouze částečně. Jsou to následující omezení:

  • Obecné typy nesmí používat [Export] nebo [ExportField]. Pokus o to vygeneruje XA4207 chybu.

    public abstract class Parcelable<T> : Java.Lang.Object, IParcelable
    {
        // Invalid; generates XA4207
        [ExportField ("CREATOR")]
        public static IParcelableCreator CreateCreator ()
        {
            ...
    }
    
  • Obecné metody nesmí používat [Export] nebo [ExportField]:

    public class Example : Java.Lang.Object
    {
    
        // Invalid; generates XA4207
        [Export]
        public static void Method<T>(T value)
        {
            ...
        }
    }
    
  • [ExportField] nelze použít pro metody, které vracejí void:

    public class Example : Java.Lang.Object
    {
        // Invalid; generates XA4208
        [ExportField ("CREATOR")]
        public static void CreateSomething ()
        {
        }
    }
    
  • Instance obecných typů nesmí být vytvořeny z kódu Jazyka Java. Dají se bezpečně vytvářet jenom ze spravovaného kódu:

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

Částečná podpora obecných typů v Javě

Podpora vazeb obecných typů Java je omezená. Zejména členové obecné třídy instance, která je odvozena z jiné obecné (non-instanceiated) třídy jsou ponechány jako Java.Lang.Object. Například Metoda Android.Content.Intent.GetParcelableExtra vrátí Java.Lang.Object. Důvodem je vymazání obecných typů Javy. Máme některé třídy, které toto omezení nepoužívají, ale jsou ručně upraveny.