Aracılığıyla paylaş


Android'de bağlama

Xamarin.Android uygulamaları, uygulamanın boyutunu küçültmek için bağlayıcı kullanır. Bağlayıcı, hangi derlemelerin gerçekten kullanıldığını, hangi türlerin gerçekten kullanıldığını ve hangi üyelerin gerçekten kullanıldığını belirlemek için uygulamanızın statik analizini kullanır. Bağlayıcı daha sonra, başvurulan derlemelerin, türlerin ve üyelerin tamamı bulunana kadar başvurulan derlemeleri, türleri ve üyeleri sürekli arayan bir çöp toplayıcı gibi davranır. Ardından bu kapatma dışındaki her şey atılır.

Örneğin Hello Android örneği:

Yapılandırma 1.2.0 Boyut 4.0.1 Boyut
Bağlama olmadan yayın: 14,0 MB 16,0 MB
Bağlama ile yayın: 4,2 MB 2,9 MB

Bağlantı, 1.2.0'da özgün (bağlantısız) paketin %30 boyutuna ve 4.0.1'de bağlantısız paketin %18'ine sahip bir paketle sonuçlanır.

Control

Bağlama, statik analizi temel alır. Sonuç olarak, çalışma zamanı ortamına bağlı olan herhangi bir şey algılanamaz:

// To play along at home, Example must be in a different assembly from MyActivity.
public class Example {
    // Compiler provides default constructor...
}

[Activity (Label="Linker Example", MainLauncher=true)]
public class MyActivity {
    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        // Will this work?
        var o = Activator.CreateInstance (typeof (ExampleLibrary.Example));
    }
}

Bağlayıcı Davranışı

Bağlayıcıyı denetlemeye yönelik birincil mekanizma, Proje Seçenekleri iletişim kutusundaki Bağlayıcı Davranışı (Visual Studio'da Bağlama) açılan listesidir. Üç seçenek vardır:

  1. Bağlama (Visual Studio'da Yok )
  2. SDK Derlemelerini Bağlama (Yalnızca Sdk Derlemeleri)
  3. Tüm Derlemeleri Bağlama (Sdk ve Kullanıcı Derlemeleri)

Bağlama seçeneği bağlayıcıyı kapatır; yukarıdaki "Bağlama olmadan yayın" uygulama boyutu örneğinde bu davranış kullanılmıştır. Bu, bağlayıcının sorumlu olup olmadığını görmek için çalışma zamanı hatalarını gidermek için yararlıdır. Bu ayar genellikle üretim derlemeleri için önerilmez.

SDK Derlemelerini Bağla seçeneği yalnızca Xamarin.Android ile birlikte gelen derlemeleri bağlar. Diğer tüm derlemeler (kodunuz gibi) bağlı değildir.

Tüm Bütünleştirilmiş Kodları Bağla seçeneği tüm derlemeleri bağlar; başka bir deyişle statik başvuru yoksa kodunuz da kaldırılabilir.

Yukarıdaki örnek, BAĞLAMA ve BAĞLAMA SDK Derlemeleri seçenekleriyleçalışır ve Tüm Derlemeleri Bağla davranışıyla başarısız olur ve aşağıdaki hatayı oluşturur:

E/mono    (17755): [0xafd4d440:] EXCEPTION handling: System.MissingMethodException: Default constructor not found for type ExampleLibrary.Example.
I/MonoDroid(17755): UNHANDLED EXCEPTION: System.MissingMethodException: Default constructor not found for type ExampleLibrary.Example.
I/MonoDroid(17755): at System.Activator.CreateInstance (System.Type,bool) <0x00180>
I/MonoDroid(17755): at System.Activator.CreateInstance (System.Type) <0x00017>
I/MonoDroid(17755): at LinkerScratch2.Activity1.OnCreate (Android.OS.Bundle) <0x00027>
I/MonoDroid(17755): at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) <0x00057>
I/MonoDroid(17755): at (wrapper dynamic-method) object.95bb4fbe-bef8-4e5b-8e99-ca83a5d7a124 (intptr,intptr,intptr) <0x00033>
E/mono    (17755): [0xafd4d440:] EXCEPTION handling: System.MissingMethodException: Default constructor not found for type ExampleLibrary.Example.
E/mono    (17755):
E/mono    (17755): Unhandled Exception: System.MissingMethodException: Default constructor not found for type ExampleLibrary.Example.
E/mono    (17755):   at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00000] in <filename unknown>:0
E/mono    (17755):   at System.Activator.CreateInstance (System.Type type) [0x00000] in <filename unknown>:0
E/mono    (17755):   at LinkerScratch2.Activity1.OnCreate (Android.OS.Bundle bundle) [0x00000] in <filename unknown>:0
E/mono    (17755):   at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState) [0x00000] in <filename unknown>:0
E/mono    (17755):   at (wrapper dynamic-method) object:95bb4fbe-bef8-4e5b-8e99-ca83a5d7a124 (intptr,intptr,intptr)

Kodu Koruma

Bağlayıcı bazen korumak istediğiniz kodu kaldırır. Örneğin:

  • aracılığıyla System.Reflection.MemberInfo.Invokedinamik olarak çağırdığınız kodunuz olabilir.

  • Türleri dinamik olarak oluşturursanız, türlerinizin varsayılan oluşturucusunun korunmasını isteyebilirsiniz.

  • XML serileştirmesi kullanıyorsanız, türlerinizin özelliklerini korumak isteyebilirsiniz.

Bu gibi durumlarda Android.Runtime.Preserve özniteliğini kullanabilirsiniz. Uygulama tarafından statik olarak bağlı olmayan her üye kaldırılabilir, bu nedenle bu öznitelik statik olarak başvurulmayan ancak uygulamanız tarafından hala gerekli olan üyeleri işaretlemek için kullanılabilir. Bu özniteliği bir türün her üyesine veya türün kendisine uygulayabilirsiniz.

Aşağıdaki örnekte, bu öznitelik sınıfın Example oluşturucuyu korumak için kullanılır:

public class Example
{
    [Android.Runtime.Preserve]
    public Example ()
    {
    }
}

Türün tamamını korumak istiyorsanız, aşağıdaki öznitelik söz dizimini kullanabilirsiniz:

[Android.Runtime.Preserve (AllMembers = true)]

Örneğin, aşağıdaki kod parçasında sınıfın tamamı Example XML serileştirmesi için korunur:

[Android.Runtime.Preserve (AllMembers = true)]
class Example
{
    // Compiler provides default constructor...
}

Bazen belirli üyeleri korumak istersiniz, ancak yalnızca içeren tür korunduysa. Bu gibi durumlarda, aşağıdaki öznitelik söz dizimini kullanın:

[Android.Runtime.Preserve (Conditional = true)]

Xamarin kitaplıklarına bağımlılık almak istemiyorsanız (örneğin, platformlar arası taşınabilir sınıf kitaplığı (PCL) oluşturuyorsanız) özniteliğini Android.Runtime.Preserve kullanmaya devam edebilirsiniz. Bunu yapmak için ad alanı içinde Android.Runtime aşağıdaki gibi bir PreserveAttribute sınıf bildirin:

namespace Android.Runtime
{
    public sealed class PreserveAttribute : System.Attribute
    {
        public bool AllMembers;
        public bool Conditional;
    }
}

Yukarıdaki örneklerde, Preserve öznitelik ad alanında Android.Runtime bildirilir; ancak bağlayıcı bu özniteliği tür adına göre aradığından özniteliğini herhangi bir ad alanında kullanabilirsiniz Preserve .

falseflag

[Preserve] özniteliği kullanılamıyorsa, bağlayıcının türün kullanıldığına inanması için bir kod bloğu sağlamak ve kod bloğunun çalışma zamanında yürütülmesini engellemek genellikle yararlıdır. Bu tekniği kullanmak için şunları yapabiliriz:

[Activity (Label="Linker Example", MainLauncher=true)]
class MyActivity {

#pragma warning disable 0219, 0649
    static bool falseflag = false;
    static MyActivity ()
    {
        if (falseflag) {
            var ignore = new Example ();
        }
    }
#pragma warning restore 0219, 0649

    // ...
}

linkskip

AndroidLinkSkip MSBuild özelliği kullanılarak diğer kullanıcı derlemelerinin Bağlantı SDK Derlemeleri davranışıyla atlanması sağlanırken, kullanıcı tarafından sağlanan bir dizi derlemenin hiç bağlanmaması gerektiğini belirtmek mümkündür:

<PropertyGroup>
    <AndroidLinkSkip>Assembly1;Assembly2</AndroidLinkSkip>
</PropertyGroup>

LinkDescription

@(LinkDescription)Derleme eylemi, Özel bağlayıcı yapılandırma dosyası içerebilen dosyalarda kullanılabilir. denetleyin. Korumak için özel bağlayıcı yapılandırma dosyaları veya private korunması internal gereken üyeler gerekebilir.

Özel Öznitelikler

Bir derleme bağlandığında, aşağıdaki özel öznitelik türleri tüm üyelerden kaldırılır:

  • System.ObsoleteAttribute
  • System.MonoDocumentationNoteAttribute
  • System.MonoExtensionAttribute
  • System.MonoInternalNoteAttribute
  • System.MonoLimitationAttribute
  • System.MonoNotSupportedAttribute
  • System.MonoTODOAttribute
  • System.Xml.MonoFIXAttribute

Bir derleme bağlandığında, Aşağıdaki özel öznitelik türleri Yayın derlemelerindeki tüm üyelerden kaldırılır:

  • System.Diagnostics.DebuggableAttribute
  • System.Diagnostics.DebuggerBrowsableAttribute
  • System.Diagnostics.DebuggerDisplayAttribute
  • System.Diagnostics.DebuggerHiddenAttribute
  • System.Diagnostics.DebuggerNonUserCodeAttribute
  • System.Diagnostics.DebuggerStepperBoundaryAttribute
  • System.Diagnostics.DebuggerStepThroughAttribute
  • System.Diagnostics.DebuggerTypeProxyAttribute
  • System.Diagnostics.DebuggerVisualizerAttribute