다음을 통해 공유


제한 사항

Android의 애플리케이션은 빌드 프로세스 중에 Java 프록시 형식을 생성해야 하므로 런타임에 모든 코드를 생성할 수 없습니다.

다음은 데스크톱 Mono에 비해 Xamarin.Android 제한 사항입니다.

제한된 동적 언어 지원

Android 런타임에서 관리 코드를 호출해야 할 때마다 Android 호출 가능 래퍼 가 필요합니다. Android 호출 가능 래퍼는 IL의 정적 분석을 기반으로 컴파일 시간에 생성됩니다. 따라서 컴파일 시간에 이러한 동적 형식을 추출하여 필요한 Android 호출 가능 래퍼를 생성할 방법이 없으므로 Java 형식의 서브클래싱(간접 서브클래싱 포함)이 필요한 시나리오에서는 동적 언어(IronPython, IronRuby 등)를 사용할 수 없습니다 .

제한된 Java 생성 지원

Java 코드가 관리 코드를 호출하려면 Android 호출 가능 래퍼 를 생성해야 합니다. 기본적으로 Android 호출 가능 래퍼에는 가상 Java 메서드를 재정의하는 (특정) 선언된 생성자 및 메서드만 포함되거나 Java 인터페이스 메서드를 RegisterAttribute구현합니다(인터페이스와 마찬가지로 Attribute).

4.1 릴리스 이전에는 추가 메서드를 선언할 수 없었습니다. 4.1 릴리스에서는 Export 사용자 ExportField 지정 특성을 사용하여 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

해결 방법은 기본 생성자를 선언하고, 로 표시하고, 다음을 ExportAttributeExportAttribute.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 ()
        {
            ...
    }
    
  • 제네릭 메서드는 사용하거나 [ExportField]다음을 사용할 [Export] 수 없습니다.

    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 코드에서 만들어서는 안 됩니다. 관리 코드에서만 안전하게 만들 수 있습니다.

    [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 제네릭 때문입니다. 이 제한을 적용하지 않는 몇 가지 클래스가 있지만 수동으로 조정됩니다.