Anmerkung
Der Zugriff auf diese Seite erfordert eine Genehmigung. Du kannst versuchen, dich anzumelden oder die Verzeichnisse zu wechseln.
Der Zugriff auf diese Seite erfordert eine Genehmigung. Du kannst versuchen , die Verzeichnisse zu wechseln.
Da Anwendungen unter Android das Generieren von Java-Proxytypen während des Buildvorgangs erfordern, ist es nicht möglich, den gesamten Code zur Laufzeit zu generieren.
Dies sind die Xamarin.Android-Einschränkungen im Vergleich zu Desktop Mono:
Unterstützung für eingeschränkte dynamische Sprache
Aufrufbare Wrapper für Android sind immer erforderlich, wenn die Android-Runtime verwalteten Code aufrufen muss. Android-aufrufbare Wrapper werden zur Kompilierzeit generiert, basierend auf der statischen Analyse von IL. Das Nettoergebnis: Sie können keine dynamischen Sprachen (IronPython, IronRuby usw.) in jedem Szenario verwenden, in dem eine Unterklasse von Java-Typen erforderlich ist (einschließlich indirekter Unterklassen), da es keine Möglichkeit gibt, diese dynamischen Typen zur Kompilierzeit zu extrahieren, um die erforderlichen aufrufbaren Android-Wrapper zu generieren.
Eingeschränkte Unterstützung der Java-Generierung
Android Callable Wrapper müssen generiert werden, damit Java-Code verwalteten Code aufrufen kann. Standardmäßig enthalten aufrufbare Android-Wrapper nur (bestimmte) deklarierte Konstruktoren und Methoden, die eine virtuelle Java-Methode überschreiben (d. h. sie hat RegisterAttribute) oder eine Java-Schnittstellenmethode implementieren (die Schnittstelle hat Attributeebenfalls ).
Vor version 4.1 konnten keine zusätzlichen Methoden deklariert werden. Ab Version 4.1 können die Export benutzerdefinierten Attribute und ExportField zum Deklarieren von Java-Methoden und -Feldern im Android Callable Wrapper verwendet werden.
Fehlende Konstruktoren
Konstruktoren bleiben schwierig, es sei denn ExportAttribute , sie werden verwendet. Der Algorithmus zum Generieren von android-aufrufbaren Wrapperkonstruktoren ist, dass ein Java-Konstruktor ausgegeben wird, wenn:
- Es gibt eine Java-Zuordnung für alle Parametertypen
- Die Basisklasse deklariert denselben Konstruktor– Dies ist erforderlich, da der aufrufbare Android-Wrapper den entsprechenden Basisklassenkonstruktor aufrufen muss . Es können keine Standardargumente verwendet werden (da es keine einfache Möglichkeit gibt, zu bestimmen, welche Werte in Java verwendet werden sollen).
Betrachten Sie beispielsweise die folgende Klasse:
[Service]
class MyIntentService : IntentService {
public MyIntentService (): base ("value")
{
}
}
Dies sieht zwar vollkommen logisch aus, aber der resultierende aufrufbare Android-Wrapper in Releasebuilds enthält keinen Standardkonstruktor. Wenn Sie also versuchen, diesen Dienst zu starten (z. B. Context.StartServiceschlägt dies fehl:
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
Die Problemumgehung besteht darin, einen Standardkonstruktor zu deklarieren, ihn mit dem ExportAttributezu versehen und festzulegen ExportAttribute.SuperStringArgument:
[Service]
class MyIntentService : IntentService {
[Export (SuperArgumentsString = "\"value\"")]
public MyIntentService (): base("value")
{
}
// ...
}
Generische C#-Klassen
Generische C#-Klassen werden nur teilweise unterstützt. Es gelten die folgenden Einschränkungen:
Generische Typen dürfen nicht oder
[ExportFieldverwenden[Export]. Der Versuch, dies zu tun, führt zu einemXA4207Fehler.public abstract class Parcelable<T> : Java.Lang.Object, IParcelable { // Invalid; generates XA4207 [ExportField ("CREATOR")] public static IParcelableCreator CreateCreator () { ... }Generische Methoden dürfen nicht oder
[ExportField]verwenden[Export]:public class Example : Java.Lang.Object { // Invalid; generates XA4207 [Export] public static void Method<T>(T value) { ... } }[ExportField]darf nicht für Methoden verwendet werden, die folgendes zurückgebenvoid:public class Example : Java.Lang.Object { // Invalid; generates XA4208 [ExportField ("CREATOR")] public static void CreateSomething () { } }Instanzen generischer Typen dürfen nicht aus Java-Code erstellt werden. Sie können nur sicher aus verwaltetem Code erstellt werden:
[Activity (Label="Die!", MainLauncher=true)] public class BadGenericActivity<T> : Activity { protected override void OnCreate (Bundle bundle) { base.OnCreate (bundle); } }
Teilweise Java Generics-Unterstützung
Die Java Generics-Bindungsunterstützung ist begrenzt. Insbesondere werden Member in einer generischen instance-Klasse, die von einer anderen generischen (nicht instanziierten) Klasse abgeleitet ist, als Java.Lang.Object verfügbar gemacht. Die Android.Content.Intent.GetParcelableExtra-Methode gibt beispielsweise Java.Lang.Object zurück. Dies ist auf gelöschte Java-Generika zurückzuführen. Es gibt einige Klassen, die diese Einschränkung nicht anwenden, aber sie werden manuell angepasst.